2👍
Alright, this is a (little) bit tricky. When working with v-model in a template loop we have to make sure the assigned model is different for each iteration. Otherwise all inputs will be bound to the exact same model instance.
We can achieve this by using an object that stores all models and access those by a key available in the loop.
Here’s some code (based on your snippet):
<template>
<div>
<div>{{ credits }}</div>
<div v-for="meal in meals">
<input :id="meal" v-model.number="creditsPerMeal[meal]" type="number">
</div>
<div>
Credits used: {{creditsSum}}
</div>
</div>
</template>
<script>
export default {
name: 'test-component',
data: function () {
let meals = [
'pizza', 'pasta', 'salad'
]
let creditsPerMeal = {}
for (let meal of meals) {
creditsPerMeal[meal] = 0
}
return {
credits: 10,
meals,
creditsPerMeal
}
},
computed: {
creditsSum () {
return Object.values(this.creditsPerMeal).reduce((a, b) => a + b, 0)
}
}
}
</script>
The tricky part is that the object which should store our models has to be pre-initialized with all keys. If this is not the case, the computed property creditsSum
would not get updated.
Keep in mind that this might not work if you get the meals dynamically via a prop or some other means. If you have to do that, consider using a watch function instead of the computed property I used in the snippet.
See this part of the documentation for more information about the change detection of Vue and this part about computed properties vs watchers.
Edit:
In case you are not using a transpiler like Babel you might have to replace all let
with var
and the loop as follows in the snippet above:
var meals = [
'pizza', 'pasta', 'salad'
]
var creditsPerMeal = {}
for (var i = 0; i < meals.length; i++) {
creditsPerMeal[meals[i]] = 0
}