27

My data object:

data: {
    selected: {
        'type': null,
        'instrument': null
    },

My template:

<select v-model="selected['instrument']" @change="switchFilter('instrument', $event)">
    <option v-for="instrument in instruments" :value="instrument.value">@{{ instrument.text }}</option> 
</select>

<select v-model="selected['type']" @change="switchFilter('type', $event)">
    <option v-for="type in types" :value="type.value">@{{ type.text }}</option> 
</select>

How can I watch both selected indexes at the same time? I want to do something like this everytime any of the indexes updates:

watch: {
    selected: function(o, n) {
        ...
    }
}
Saurabh
  • 71,488
  • 40
  • 181
  • 244
Anonymous
  • 850
  • 2
  • 12
  • 26

3 Answers3

33

You can use deep option provided by the watcher from vue. As stated in the docs:

To also detect nested value changes inside Objects, you need to pass in deep: true in the options argument. Note that you don’t need to do so to listen for Array mutations.

You code will look like following:

watch: {
    'selected': {
        handler: function (val, oldVal) {
            console.log('watch 1', 'newval: ', val, '   oldVal:', oldVal)
        },
        deep: true
    }
}
tony19
  • 125,647
  • 18
  • 229
  • 307
Saurabh
  • 71,488
  • 40
  • 181
  • 244
30

I think you can do this:

watch: {
    $data: {
        handler: function(val, oldVal) {
            console.log(val)
        },
        deep: true
    }
},
  • 8
    I think this answer still adds a new angle. DRY and elegant. :) – Eerik Sven Puudist Jan 16 '19 at 22:17
  • 2
    @Anonymous - His answer is more than fine and not remotely unnecessary: it shows it's possible to watch the built-in `data` object, which no other answer demonstrated. – Dan Oct 23 '19 at 01:31
  • 1
    Didn't know about the ```deep: true```, works great! Also very clean when you destruct the parameter object, like ```handler: function({ value1, value2 })``` (ES6). My only concern is that it is watching everything in $data. Anyone knows how to watch the destructed parameters only? Writing seperate watchers just don't feel DRY. – Justin La France Apr 06 '20 at 10:18
  • I think this is what you're looking for: https://stackoverflow.com/questions/42133894/vue-js-how-to-properly-watch-for-nested-data –  Apr 15 '20 at 19:22
11
watch: {
  'selected.type': function (newSelectedType) {
    console.log(newSelectedType)
  },

  'selected.instrument': function (newSelectedinstrument) {
    console.log(newSelectedinstrument)
  }
}

If you are just trying to calculate a new data from selected, you can just use computed properties, since the data of Vue are reactive, the computed properties can also detect the changes of data.


If you want to use a single function to watch the entire object, you can use $watch with deep: true:

mounted () {
  this.$watch('$data.selected', this.onSelectedUpdate, { deep: true })
}

note that '$data.selected' is a string, Vue will parse it.

and in your methods:

onSelectedUpdate (newSelected) {
  console.log(newSelected)
}
CodinCat
  • 15,530
  • 5
  • 49
  • 60