Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array watch with Vue.js 2

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.

like image 226
Corwin Avatar asked Dec 17 '16 17:12

Corwin


People also ask

How do I watch an array in Vue?

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.

Is Vue 2 deprecated?

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.

How do you watch objects in Vue?

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 .

How do you trigger a watch in Vue?

To trigger the Vue watch method, you should assign a new city name to the value property of the ref object.


2 Answers

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.

like image 104
Lukasz Wiktor Avatar answered Oct 03 '22 03:10

Lukasz Wiktor


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}
}
like image 41
Saurabh Avatar answered Oct 03 '22 03:10

Saurabh