I'm having a set of selects (item.pricelists that are assigned to an item) rendered in a v-for loop and bound with v-model. Possible select options for that item are rendered with another v-for from item.valid_pricelists. Both are pulled from the server in the same array. Now I need to watch for when user changes selection , so i can update the item.pricelists array with new values from item.valid_pricelists.
Render part :
<div v-for="(row,index) in item.pricelists">
<select v-model="row.id">
<option :value="price_list.id" v-for="price_list in item.valid_pricelists">
{{price_list.description}}
</option>
</select>
Parent pricelist : {{row.parent_id}}
</div>
Watch part :
watch:{
'item.pricelists.id': {
handler: function (val,oldVal) {
console.log(val + " - " + oldVal);
}, deep:true}
}
Now, watch - that works just fine for simple vars - refuses to budge.
Here's the fiddle with relevant part of the code.
I was looking at the vue docs, but can't wrap my head around it. Any help would be appreciated.
You need to set deep to true when watching an array or object so that Vue knows that it should watch the nested data for changes. Join 11,067 other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.
Vue 2 has now entered maintenance mode: it will no longer ship new features, but will continue to receive critical bug fixes and security updates for 18 months starting from the 2.7 release date. This means Vue 2 will reach End of Life by the end of 2023.
Deep watcher over array of objects. vue , we have to import it in the App. vue file and pass users as a prop . In User. vue , we are using watcher over the value which is changing and we are also using user.name property instead of user so that vue can detect the change happening to user.name .
To trigger the Vue watch method, you should assign a new city name to the value property of the ref object.
I don't know if it's possible to solve this with watch, however, I would suggest another approach. You could add v-on:change
to your selects:
<select v-model="row.id" v-on:change="selectionChanged(row)">
and add a method to the Vue instance:
new Vue({
...
methods: {
selectionChanged: function(item) {
}
}
}
This way you will know that selection has changed whenever the selectionChanged
function is called.
You can actually set watcher on array variable, the problem with your approach is you have set watcher on item.pricelists.id
, but item.pricelists
is an array so you can not directly access id
on this.
You can set a watcher on complete array like following(see fiddle):
watch:{
'item.pricelists': {
handler: function (val,oldVal) {
console.log(val + " - " + oldVal);
}, deep:true}
}
Note:
Caveat with this approach is as explained in the docs:
When mutating (rather than replacing) an Object or an Array, the old value will be the same as new value because they reference the same Object/Array. Vue doesn’t keep a copy of the pre-mutate value.
If you want oldValue as well as new value, you can look this fiddle using Vue.set as explained here.
You can also set watcher on individual element of array like following(see fiddle):
watch:{
'item.pricelists.0.id': {
handler: function (val,oldVal) {
console.log(val + " - " + oldVal);
}, deep:true}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With