[Vuejs]-VueJS 2 – Watch properties inside arrays and/or objects

0πŸ‘

βœ…

If you make your total a computed property then you get a lot more reactivity for free (meaning you don’t have to listen for updates to the item values or explicitly recalculate anything). See the answer here for specific implementation: https://jsfiddle.net/16wk9gre/

html

<script src="https://unpkg.com/vue"></script>
<div id="app">
  <h3>Tests</h3>
  <ul>
    <li v-for="part in parts">
      <span>{{ part.name }}</span>
      <ul>
        <li v-for="item in part.items">
          R$ <input type="number" v-model="item.value">
          <button type="button" @click="onClickRemoveItem($event, part, item)">Remove</button>
        </li>
        <p>
           Part subtotal: ${{ part.items.reduce((acc, item) => acc + parseFloat(item.value), 0) }}
        </p>
        <p>
          Part subtotal (alternate): ${{ calculatePartSubtotal(part.items) }}
      </p>
      </ul>
    </li>
  </ul>

  <p><strong>Total value:</strong>R$ {{ total }}</p>
</div>

JS

new Vue({
  el: '#app',
  data() {
    return {
      // Define some nested mock data.
      parts: [
        { id: 1, name: 'Part 1', items: [{ id: 1, value: 10.00 }, { id: 2, value: 5.00 }] },
        { id: 2, name: 'Part 2', items: [{ id: 3, value: 15.00 }] }
      ]
   }
 },
computed: {
  total () {
    let total = 0.0
    for (let i = 0; i < this.parts.length; i++) {
      for (let j = 0; j < this.parts[i].items.length;; j++) {
        total += parseFloat(this.parts[i].items[j].value)
      }
    }
    return total
  }
},
methods: {
  calculatePartSubtotal (items) {
    return items.reduce((acc, item) => acc + parseFloat(item.value), 0)
  },
  // Remove an item of a part.
  onClickRemoveItem(event, part, item) {
    let index = part.items.findIndex(e => e.id === item.id)
    this.$delete(part.items, index)
   }
 }
})

Leave a comment