Would like to be able to use Alpine.js to for a dropdown select form. When you select a particular option from the select menu the page insert a set of related records. How would I accomplish something like this with Alpine.js
For example
Select from USA, Canada and Mexico from the select menu. Assume USA was selected
Retrieve a list stores in the USA. (I know I would query this via PHP, sending a param)
You could do something like this (assuming you have all the data beforehand)
<div
x-data="{ selectedCountry: null, countries: [ 'Mexico', 'USA', 'Canada' ], storesByCountry: { 'USA': [ { 'store' : 'data' } ] } }"
>
<select x-model="selectedCountry">
<template x-for="country in countries" :key="country">
<option :value="country" x-text="country"></option>
</template>
</select>
Stores:
<template x-for="store in storesByCountry[selected country] || []" :key="store.id">
</template>
</div>
If you don't have the data you'll need to do something like this
<div
x-data="{ selectedCountry: null, countries: [ 'Mexico', 'USA', 'Canada' ], stores: [ { 'store' : 'data' } ] }"
x-init="$watch('selectedCountry', (country) => { fetch('url?country=" + country).then(res=> res.json()).then((storeData) => { stores = storeData }) })"
>
<select x-model="selectedCountry">
<template x-for="country in countries" :key="country">
<option :value="country" x-text="country"></option>
</template>
</select>
Stores:
<template x-for="store in stores" :key="store.id">
</template>
</div>
Related
I have the following code which should loop over an array to populate an HTML select element but getting zero data?
<div class="w-full" x-data="{classes: [
{
room: 'online',
id: 1,
},
{
room: 'in class',
id: 2,
}
]}">
<select name="" id="">
<template x-for="class in classes" :key="class.id">
<option x-text="class.room" :value="class.room"></option>
</template>
</select>
</div>
Please check this. I renamed class to cls (may be class word is conflicting though did not see any error in concole)
https://codepen.io/rajdeepdebnath/pen/MWyNoKj?editors=1010
<div class="w-full" x-data="{classes: [
{
room: 'online',
id: 1,
},
{
room: 'in class',
id: 2,
}
]}">
<select name="" id="">
<template x-for="cls in classes" :key="cls.id">
<option x-text="cls.room" :value="cls.room"></option>
</template>
</select>
</div>
I have implemented a drop down using Laravel collectives. I need to call function setMaterialValue(let x){ console.log(x)} on each time I select a material. This should be specific to each material as cotton-10, wetlook-20, crocodile-30 etc. Without Laravel collective this can be performed as
<option onclick="setMaterialValue(10);">Cotton</option>
How to perform this using Laravel collectives?
My code is as follows:
<div class="card">
<div class="card-header"><h2 class="card-title m-0">Feature Selector</h2></div>
<div class="card-body">
<h5 class="card-title"><b>Material Selector</b></h5>
<div class="row">
<div class="col-md-6">
Textile Material
</div>
<div class="col-md-6">
{{Form::select('material_selector', [
'10' => 'Cotton',
'20' => 'Wet Look',
'30' => 'Crocodile',
], null, ['placeholder' => 'Select Material'],['class'=>'form-control'])
}}
</div>
</div>
<hr>
</div>
</div>
FYI - Where your class declaration is add it and any other html attributes there as well:
{{ Form::select('material_selector',
[
'1' => 'Cotton',
'2' => 'Wet Look',
'3' => 'Crocodile',
],
null,
['placeholder' => 'Select Material'],
[
'class'=>'form-control',
'onclick'=>'setMaterialValue(10)' // <== ADD IT HERE
])
}}
You should probably use jQuery. Then you can address your select element as follows
$(document).ready(function() {
$('.form-control[name="material_selector"]').on('change', showSelectedValue);
function showSelectedValue(event) {
var target = $(event.target);
console.log(target.val() + " = " + target.find('option:selected').text());
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select name="material_selector" class="form-control">
<option value="10">Cotton</option>
<option value="20">Wet Look</option>
<option value="30">Crocodile</option>
</select>
Another option
If you really do not want to use jQuery, then try to use the onChange attribute for the select tag like the example below
{{Form::select(
'material_selector', // name attribute of the select
['10' => 'Cotton', '20' => 'Wet Look', '30' => 'Crocodile'], // option values
null, // selected value, for example '20'
['placeholder' => 'Select Material', 'class' => 'form-control', 'onChange' => 'showSelectedValue(this)'], // attributes for <select>
)}}
function showSelectedValue(element) {
console.log(element.value + " = " + element.options[element.selectedIndex].text);
}
<select name="material_selector" class="form-control" onChange="showSelectedValue(this)">
<option value="10">Cotton</option>
<option value="20">Wet Look</option>
<option value="30">Crocodile</option>
</select>
I have build a vue-component which takes a list of objects and two criteria lists as props. The select lists are passed to two select inputs in the template. When either one is changed the list is filtered using the selected criteria. How do I get access to this filtered list in my blade file?
Here is my code.
Blade file:
<subjecttable-select :data-subjecttable="{{$subjectslessons->toJson()}}"
:data-departments="{{$departments->toJson()}}"
:data-subjects="{{$subjects->toJson()}}" #input="selectedsubjects">
</subjecttable-select>
#{{selectedsubjects}}
Vue-component
<template>
<div >
<div class="row mb-2 mx-2">
<form class="form-inline justify-content-between" >
<div class="form-group row mb-1">
<label class="col-auto col-form-label text-md-left" for="department">Leerjaar</label>
<div class="col-auto">
<select id= "department" class="form-control form-control-sm custom-select" v-model="department" #change="select()">
<option v-for="department_item in dataDepartments" :value="department_item['id']">
{{department_item["name"]}}
</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-auto col-form-label text-md-leftt" for="subject">Vak</label>
<div class="col-auto">
<select id="subject" class="form-control form-control-sm custom-select" v-model="subject" #change="select()">
<option v-for="subject_item in dataSubjects" :value="subject_item['id']">
{{subject_item["description"]}}
</option>
</select>
</div>
</div>
<button class="btn-outline-primary" #click="reset()">Reset</button>
</form>
</div>
</div>
</template>
<script>
export default {
name:"subjecttable-select",
props: {
dataDepartments: { type: Array, required: true },
dataSubjects:{ type: Array, required: true},
dataSubjecttable: {type: Array, required: true },
value:{},
},
data() {
return {
selected:this.dataSubjecttable,
subject:"",
department:"",
}
},
methods:{
select(){
var item;
console.log(this.subject);
this.selected=[];
for(item of this.dataSubjecttable){
if(//get the subbejctlessons who are in the selected department
(this.department==="" || item["department_id"]===this.department) &&
//whose subject is the selected subject
(this.subject===""|| item["subject_id"]===this.subject)
){
this.selected.push(item);
}
}
this.$emit('input',this.selected);
},
reset(){
this.value = this.dataSubjecttable;
this.subject = "";
this.department="";
},
},
created(){
this.select();
},
filters: {
dateFilter(value){
var isDate = !isNaN(Date.parse(value));
if (isDate ){
var dateValue=new Date(value);
return dateValue.toLocaleDateString();
}
else{
return value;
}
}
},
};
</script>
app.js
Vue.component('subjecttable-select', require('./components/SubjectSelection.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
});
As you can see I emit an input event in my component but I have trouble accessing the value in the blade file.
Ideally, I think you want to do is load your SelecttableSelect component within another parent Vue component. This will allow you to trickle your events down to the parent component and use the data much more easily.
I have not tested this, but it's along the lines of what I would do to get started. You would need to format the output to your needs.
Lessons.vue
<template>
<div>
<!-- YOUR SELECT IS NOW DEFINED HERE, NOT IN THE BLADE FILE -->
<!-- Select -->
<subjecttable-select :data-subjecttable="dataSubjecttable"
:data-departments="dataDepartments"
:data-subjects="dataSubjects"
#input="updateResults"
>
</subjecttable-select>
<!-- End Select -->
<!-- Department -->
<div>
<h1>Department</h1>
<div v-if="results.department_id > 0">
<ul>
<li v-for="(value, index) in findElementById(dataDepartments, results.department_id)">
{{ index }} : {{ value }}
</li>
</ul>
</div>
</div>
<!-- End Department -->
<!-- Subject -->
<div>
<h1>Subject</h1>
<div v-if="results.subject_id > 0">
<ul>
<li v-for="(value, index) in findElementById(dataSubjects, results.subject_id)">
{{ index }} : {{ value }}
</li>
</ul>
</div>
</div>
<!-- End Subject -->
</div>
</template>
<script>
// import your select component
import SubjecttableSelect from './SubjecttableSelect';
export default {
components: {
// register the component
SubjecttableSelect,
},
props: {
dataDepartments: { type: Array, required: true },
dataSubjects:{ type: Array, required: true},
dataSubjecttable: {type: Array, required: true },
},
name: "Lessons",
data() {
return {
results: {
subject_id: 0,
department_id: 0,
},
}
},
methods: {
updateResults(data) {
this.results = data;
},
findElementById(element, id) {
return element.find(el => el.id === id);
}
},
}
</script>
<style scoped>
</style>
app.js
// register the new component
Vue.component('lessons', require('./components/Lessons.vue').default);
// subjecttable-select can now be imported within lessons
const app = new Vue({
el: '#app',
});
your.blade.php (please note the single quotes)
<lessons :data-subjecttable='#json($subjectslessons)'
:data-departments='#json($departments)'
:data-subjects='#json($subjects)'>
</lessons>
I am trying to set option selected where option value is 1. But I am getting in trouble when using v-select from vuejs. This is how I am trying to do -
<v-select name="branchid" v-model="branchid"
:options="branches.map(branches => ({label: branches.label, value: branches.value}))"
:selected="branches.value === 1"></v-select>
Would someone help me please to get the option value selected when option value is 1?
I've put together a simplified version of what (I think) you're trying to do:
<template>
<div>
<div>
<select v-on:change="select($event);" value="branchid">
<option disabled value="">Please select one</option>
<option :selected="branchid === 1">1</option>
<option :selected="branchid === 2">2</option>
<option :selected="branchid === 3">3</option>
</select>
<span>Selected: {{ branchid }}</span>
<button v-on:click="selectOne">Select Option 1</button>
</div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
branchid: 0,
branchidTwo: 1
};
},
methods: {
select: function(evt) {
this.branchid = evt.target.value;
},
selectOne: function() {
this.branchid = 1;
}
}
};
</script>
This does not use the v-model pattern. The docs explicitly state that if you use v-model, the class itself will be used as the source of truth rather than value or selected. You'll see I've added a button that will set the selected option on the select component.
Hope that helps.
Initialize it with select v-model with the value you want selected
new Vue({
el: '#example',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="example">
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
Source : https://v2.vuejs.org/v2/guide/forms.html#Select
I have two components. Component 1:
<template>
<div>
<div class="form-group">
<label for="group">Category</label>
<select name="category" v-model="category" #change="setCategory(category)" class="form-control select-group" id="category">
<option value="1">Category 1</option>
<option value="2">Category 2</option>
</select>
</div>
<tags-multiselect :categoryId="category"></tags-multiselect>
</div>
</template>
<script>
export default {
data () {
return {
category: 1,
}
},
methods: {
setCategory(selected) {
this.category = selected;
},
},
}
</script>
Component 2:
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header">Example Component</div>
<div class="card-body">
I'm an example component.
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['categoryId'],
data () {
return {
category_ids: this.categoryId
}
},
created() {
axios.post('/tags', { category_id: this.categoryId })
.then((response) => {
//
})
.catch((err) => {
})
}
}
</script>
When I select option from first component, I not update category_id on second component with other id I get only 1 id. And when I send axios request with category_id I send always only first param 1. How I can resolve this? How I can refresh the second component with new selected data from select field?
props need to be kebab case in the template.
Try <tags-multiselect :category-id="category"></tags-multiselect>
Also, you don't need to redefine props in the data. Get rid of category_ids in component 2, it will just confuse things.
Then, Vue makes it very easy to extract your state from your components. Shared state (categoryId) and operations on shared state ( axios.post(...) ) would be much happier in global scope, according to me !