I am trying to create an object that contains multiple values from a v-for loop. The loop goes through an array of exercises with a predetermined amount of sets:
const exercise = [
{ id: 1, name: exercise1, sets: 3 },
{ id:2, name: exercise2, sets: 2 }
{ id:3, name: exercise3, sets: 4 }
]
I want the user to be able to enter the weight and reps for each set in each exercise and then store the data in an array.
My array and component looks something like this.
const exercisesInput = [
{
exercise: "",
sets: {
set: "",
reps: "",
weight: "",
},
},
];
<template v-for="exercise in exercises" :key="exercise.id">
<span> {{ exercise.name }} </span>
<template v-for="set in exercise.sets" :key="set">
<span> {{ set }} </span>
<input type="number" name="weight" v-model=""> </input>
<input type="number" name="reps" v-model=""> </input>
<span @click="completeSet()"> complete {{ set }} </span>
</template>
</template>
So the idea is that the user gets presented with a loop of each exercise with X amount of sets and for each set the user inserts the weight and reps and then presses a button that pushes the data to the exercisesInput array.
But I am completely stuck on how to use v-model to do this.
CodePudding user response:
Initialize your object with a property called setData which is an array of objects, each with the prop for weight and reps.
Then, in your inner v-for loop iterate over these arrays instead of the sets
number value. Setting the v-model to the appropriate prop on the iterated setData object. Also adjust your output for the fact that the setIndex is zero-based.
JS:
const exercise = [
{ id: 1, name: exercise1, sets: 3, setData: [{weight: '', reps: ''}, {weight: '', reps: ''}, {weight: '', reps: ''}]},
{ id:2, name: exercise2, sets: 2, setData: [{weight: '', reps: ''}, {weight: '', reps: ''}]}
{ id:3, name: exercise3, sets: 4, setData: [{weight: '', reps: ''}, {weight: '', reps: ''}, {weight: '', reps: ''}, {weight: '', reps: ''}] }
]
Template:
<template v-for="exercise in exercises" :key="exercise.id">
<span> {{ exercise.name }} </span>
<template v-for="(set, setIndex) in exercise.setData" :key="set">
<span> {{ setIndex 1}} </span>
<input type="number" name="weight" v-model="set.weight"> </input>
<input type="number" name="reps" v-model="set.reps"> </input>
<button @click="completeSet()"> complete {{ setIndex 1}} </button>
</template>
</template>
CodePudding user response:
You can dynamically create sets and use structure like in @WillD answer:
const app = Vue.createApp({
data() {
return {
exercises: [{ id: 1, name: 'exercise1', sets: 3 }, { id:2, name: 'exercise2', sets: 2 }, { id:3, name: 'exercise3', sets: 4 }]
};
},
methods: {
createSets() {
this.exercises = this.exercises.map(e => {
e.setData = Array.from(Array(e.sets)).map(s => {
return { weight: '', reps: '' }
})
return { ...e }
})
}
},
mounted() {
this.createSets()
}
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
<div v-for="exercise in exercises" :key="exercise.id">
<span> {{ exercise.name }} </span>
<div v-for="(set, setIndex) in exercise.setData" :key="set">
<span> {{ setIndex 1}} </span>
<input type="number" name="weight" v-model="set.weight" />
<input type="number" name="reps" v-model="set.reps" />
<button @click="completeSet()"> complete {{ setIndex 1}} </button>
</div>
</div>
{{ exercises }}
</div>