How to watch dynamically added nested properties?

Hi. Say I’ve got some data like this:

  ,data:{
    form:{
      ,screws:[]
      ,screw:{
        ,washer_type: ''
      }
  }

Then, by clicking a button on dom, I will

form.screws.push(form.screw)

Then, I need to watch for changes in washer_type of each screw.

How to?

Use Vue.set() – see https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

Thank you but it doesn’t solve my issue. Yes, I changed the code to this:

  $('.add-screw-button').on('click', function(){
    this.$set(this.form.screws, this.form.screws.length, Object.assign({},this.form.screw)); // this
  }.bind(this));

But, ok, that ensures reactivity when form.screws gets added a new screw. This worked even before, without using $set, to be true.

But what I really need is to watch for changes on the subprops of each single screw, such as the
washer_type prop. It’s an inner prop of an inner prop (screw) arbitrarily added to the main array (screws). How to?

The same principle would apply. Example:

this.$set(this.form.screws[42], 'washer_type', 'value')

(with 42 being just an example index)

Ok thank you :slight_smile: but then, what’s the right syntax for the watcher? That’s my main issue. That’s what I really cannot find in docs. Keep in mind that we do not know how many screws the user will add, so I cannot reference them by direct index in watchers.

,watch:{
    'form.screws.0.washer_type':function(e){ // and so on.. I cannot do that

Maybe the button the user clicks can transport not only the new washer_type to be set, but also the ID of the respective screw. Hard to tell if I do not know the complete data model and code.

So apparently currently no official syntax to support standard watchers in a situation like this?

My code is quite simple, a vue app without js components. Data and watchers.

const vueapp = new Vue({
  el: '.form-panels'
  ,data:{
    form:{
      ,screws:[]
      ,screw:{
        thread:'Metrica'
        ,thread_t:'Metrica'
        ,thread_image: 'filetto-metriche.png' // etc....
[...]

  ,watch:{
      // watchers
   }

You can $watch('form.screws', cb) for any changes of nested prop by passing extra option {deep:true}, but it doesnt pass to cb what property was changed. If you want to watch for each property separately, you have to set watchers using $watch('form.screw.45.washer_type', cb) at the same time when you push new screw
But it is the pain, because you have to collect unwatchers and call them all at beforeDestroy hook. So why do you need to watch? Maybe there is another way.

https://vuejs.org/v2/api/#watch

The multiple screws array is in fact a new feature. Before, I had just one screw. My original single screw watch code was this:

'form.screw.thread':function(val, oldval){
  var box = this.$refs.screw_thread_radios;
  this.form.screw.thread_t = box.querySelector('input[value="' + val + '"] + label .name').innerHTML;
  this.form.screw.thread_image = UrlUtilities.get_file_in_url(box.querySelector('input[value="' + val + '"] + label img').getAttribute('src'));
}

Basically, when some specific fields change (in this case the ‘screw.thread’ field), I need to change some other fields accordingly, modifying their values based on the screw.thread one.

That is there are some independent fields and other fields that are functions of the former, just make them computed! It is better to use computed wherever possible