Search code examples
objectvue.jswatch

How to vue watch a specific property in an array of objects


I'm using vue.js 2.5.2

I have an array of objects and I'd like to watch forms[*].selected and if it changes call a function.

This is my attempt, but obviously, it is not correct. I tried putting the array into a for loop to watch each object's property selected.

watch: {
  for (var i = 0; i < forms.length; i++) 
  {
      forms[i].selected: function(){
      console.log("change made to selection");
    }
  }
},

This is the array of objects called forms[]

forms: [
  {
    day: '12',
    month: '9',
    year: '2035',
    colors: 'lightblue',//default colour in case none is chosen
    selected: true
  },
  {
    day: '28',
    month: '01',
    year: '2017',
    colors: 'lightgreen',//default colour in case none is chosen
    selected: true
  }
],

Any help would be greatly appreciated,

Thanks


Solution

  • You could use a deep watcher, but a more elegant solution would be to create computed property of the data you want to watch, and watch that instead:

    new Vue({
      el: '#app',
      data: () => ({
        forms: [{
            day: '12',
            month: '9',
            year: '2035',
            colors: 'lightblue',
            selected: true
          },
          {
            day: '28',
            month: '01',
            year: '2017',
            colors: 'lightgreen',
            selected: true
          }
        ],
      }),
      computed: {
        selected() {
          return this.forms.map(form => form.selected)
        }
      },
      watch: {
        selected(newValue) {
          console.log("change made to selection")
        }
      }
    })
    <html>
    
    <head>
      <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>
    
    <body>
    
      <div id="app">
        <ul>
          <li v-for="(form, i) in forms" :key="i">
            <input type="checkbox" v-model="form.selected"> {{form.colors}}
          </li>
        </ul>
      </div>
    
    </body>
    
    </html>