Vue change object in array and trigger reactivity

shanemgrey picture shanemgrey · Oct 28, 2017 · Viewed 31.4k times · Source

How can I trigger an update when altering part of an object found by index in an array?

The docs show how to alter the value of an array:

Vue.set(example1.items, indexOfItem, newValue)

or

example1.items.splice(indexOfItem, 1, newValue)

But how to alter the value of a property on an object in an array without changing the rest of the object?

The following works to update the property, but Vue doesn't react to the change until something else triggers an update.

example1.items[indexOfItem].some_object_property = false

Answer

tony19 picture tony19 · Oct 28, 2017

You could update the sub-property in the array element with this.$set(). For example, to increment an x subproperty in the first two array elements (creating the sub-property if it doesn't exist):

methods: {
  update() {
    this.$set(this.arr[0].foo, 'x', (this.arr[0].foo.x || 0) + 100)
    this.$set(this.arr[1].foo, 'x', (this.arr[1].foo.x || 0) + 100)
  }
}

new Vue({
  el: '#app',
  data() {
    return {
      arr: [
        {
          foo: {
            x: 100,
            y: 200
          }
        },
        {
          foo: {
            /* x does not exist here initially */
            y: 400
          }
        }
      ]
    };
  },

  methods: {
    update() {
      this.$set(this.arr[0].foo, 'x', (this.arr[0].foo.x || 0) + 100)
      this.$set(this.arr[1].foo, 'x', (this.arr[1].foo.x || 0) + 100)
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <button @click="update">Update</button>
  <p>arr[0]: {{ arr[0] }}</p>
  <p>arr[1]: {{ arr[1] }}</p>
</div>

codepen