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)
}
}
})
Source:stackexchange.com