Reputation: 697
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.
Upvotes: 6
Views: 10327
Reputation: 73669
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}
}
Upvotes: 4
Reputation: 20422
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.
Upvotes: 4