7

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.

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I actually had that at some point, but for some obscure reason wanted to know the value before the change. This made me stop fiddling with the watcher and rethink data flow once more. Works like a charm
4

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}
}

3 Comments

Good to know. But in the first example the return values are always the same (val = oldval) ?
@Corwin I have updated the answer as par your query.
how to get index of changed item?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.