0👍
✅
Instead of calling update
in the watchers for shop
and nonShop
, just add a change
event handler to the selects
to call update
that way instead:
<select v-model="input.value" @change="update">...</select>
This way, the update
method will be called whenever the user changes the value of an input, not when the value of an input gets updated by Vue.
Here’s a full working example:
Vue.config.devtools = false;
Vue.config.productionTip = false;
let vueApp = new Vue ({
el: '#app',
data() {
return {
inputs: [{
name: 'shop',
value: 'all',
options: [
{id: 'all', name: 'All shops'},
{id: 1, name: 'Shop 1'},
{id: 2, name: 'Shop 2'},
{id: 3, name: 'Shop 3'}
]
}, {
name: 'country',
value: 'all',
options: [
{id: 'all', name: 'All countries'},
{id: 1, name: 'Country 1'},
{id: 2, name: 'Country 2'},
{id: 3, name: 'Country 3'}
]
}, {
name: 'gender',
value: 'all',
options: [
{id: 'all', name: 'All genders'},
{id: 1, name: 'Gender 1'},
{id: 2, name: 'Gender 2'},
{id: 3, name: 'Gender 3'}
]
}]
};
},
computed: {
shop() {
return this.inputs.filter(d => d.name === 'shop')[0].value;
}
},
watch: {
shop() {
$.when((async function() {
setTimeout(() => {
let newCountries = [];
for (let i = 1; i < 4; i++) {
let rand = Math.floor(Math.random() * 100);
newCountries.push({id: rand, name: 'Country: ' + rand});
let countryObject = vueApp.inputs.filter(d => d.name === 'country')[0];
countryObject.options = [{id: 'all', name: 'All countries'}, ...newCountries];
countryObject.value = 'all';
}
}, 200);
})(), (async function() {
setTimeout(() => {
let newGenders = [];
for (let i = 1; i < 4; i++) {
let rand = Math.floor(Math.random() * 100);
newGenders.push({id: rand, name: 'Gender: ' + rand});
let genderObject = vueApp.inputs.filter(d => d.name === 'gender')[0];
genderObject.options = [{id: 'all', name: 'All genders'}, ...newGenders];
genderObject.value = 'all';
}
}, 100);
})());
},
},
methods: {
update() {
console.log('updating');
}
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='app'>
<div style='list-style-type: none' v-for="input in inputs">
<p><b>{{ input.name }}</b></p>
<select v-model="input.value" @change="update">
<option v-for="option in input.options" :value="option.id" >{{ option.name }}</option>
</select>
</div>
</div>
If you need the country
and gender
values to change before calling the update
method, then add a separate method as a handler for the change
event to set the new country
and gender
values and then call the update
method after that has finished.
Here’s and example of that:
Vue.config.devtools = false;
Vue.config.productionTip = false;
let vueApp = new Vue ({
el: '#app',
data() {
return {
inputs: [{
name: 'shop',
value: 'all',
options: [
{id: 'all', name: 'All shops'},
{id: 1, name: 'Shop 1'},
{id: 2, name: 'Shop 2'},
{id: 3, name: 'Shop 3'}
]
}, {
name: 'country',
value: 'all',
options: [
{id: 'all', name: 'All countries'},
{id: 1, name: 'Country 1'},
{id: 2, name: 'Country 2'},
{id: 3, name: 'Country 3'}
]
}, {
name: 'gender',
value: 'all',
options: [
{id: 'all', name: 'All genders'},
{id: 1, name: 'Gender 1'},
{id: 2, name: 'Gender 2'},
{id: 3, name: 'Gender 3'}
]
}]
};
},
computed: {
shop() {
return this.inputs.filter(d => d.name === 'shop')[0].value;
}
},
methods: {
onChange(name) {
if (name === 'shop') {
$.when((async function() {
setTimeout(() => {
let newCountries = [];
for (let i = 1; i < 4; i++) {
let rand = Math.floor(Math.random() * 100);
newCountries.push({id: rand, name: 'Country: ' + rand});
let countryObject = vueApp.inputs.filter(d => d.name === 'country')[0];
countryObject.options = [{id: 'all', name: 'All countries'}, ...newCountries];
countryObject.value = 'all';
}
}, 200);
})(), (async function() {
setTimeout(() => {
let newGenders = [];
for (let i = 1; i < 4; i++) {
let rand = Math.floor(Math.random() * 100);
newGenders.push({id: rand, name: 'Gender: ' + rand});
let genderObject = vueApp.inputs.filter(d => d.name === 'gender')[0];
genderObject.options = [{id: 'all', name: 'All genders'}, ...newGenders];
genderObject.value = 'all';
}
}, 100);
})()).then(this.update);
} else {
this.update()
}
},
update() {
console.log('updating');
}
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='app'>
<div style='list-style-type: none' v-for="input in inputs">
<p><b>{{ input.name }}</b></p>
<select v-model="input.value" @change="onChange(input.name)">
<option v-for="option in input.options" :value="option.id" >{{ option.name }}</option>
</select>
</div>
</div>
Source:stackexchange.com