Home > Net >  Setting value for each item in for loop to true or false
Setting value for each item in for loop to true or false

Time:08-29

I am trying to create a v-for that shows a list of exercises containing several sets. I have created a loop with a row for each set underneath each exercise.

my data looks like this.

const exercises = [ 
{ id: 1, name: exercise1, sets: 3 },
{ id:2, name: exercise2, sets: 2 } 
{ id:3, name: exercise3, sets: 4 } 
]

And my component looks something like this:

 <template v-for="exercise in exercises" :key="exercise.id">
   <span> {{ exercise.name }} </span>
    <template v-for="set in exercise.sets" :key="set">
      <span @click="completeSet()"> {{ set }} </span>
    </template>
  </template>

Now I want to be able to mark each set as completed by setting the value on each set to either true or false through a click event. But I am not sure about how to do this since each set doesn't have a property to set a value because it's looping through a number.

What would be the right approach to this problem?

CodePudding user response:

First and foremost, you can't loop through a number. To be able to loop the sets, you'd have to

<template v-for="let set = 0; set < exercise.sets; set  " :key="set">
    <span @click="completeSet()"> {{ set }} </span>
</template>

However, setting a property on a number is equally impossible. You have to prepare your data to be able to make that adjustment:

const exercises = [ 
{ id: 1, name: 'exercise1', sets: 3 },
{ id: 2, name: 'exercise2', sets: 2 } ,
{ id: 3, name: 'exercise3', sets: 4 } 
].map(exercise => ({
    id: exercise.id,
    name: exercise.name,
    sets: Array.from(
        { length: exercise.sets },
        () => ({ completed: false })
    ),
}))

CodePudding user response:

You can create array with finished sets and compare it (try the snippet pls):

new Vue({
  el: "#demo",
  data() {
    return {
      exercises: [{ id: 1, name: 'exercise1', sets: 3 }, { id: 2, name: 'exercise2', sets: 2 }, { id: 3, name: 'exercise3', sets: 4 }],
      finishedSets: []
    }
  },
  methods: {
    compareObjects(o1, o2) {
      return Object.entries(o1).sort().toString() !== Object.entries(o2).sort().toString()
    },
    findObject(id, set) {
      return this.finishedSets.find(f => f.id === id && f.set === set)
    },
    completeSet(id, set) {
      this.findObject(id, set) ? 
        this.finishedSets = this.finishedSets.filter(f => {return this.compareObjects(f, this.findObject(id, set))}) :
        this.finishedSets.push({id, set})
    },
    isFinished(id, set) {
      return this.findObject(id, set) ? true : false
    }
  }
})
.set {
  width: 70px;
  cursor: pointer;
}
.finished {
  background-color: seagreen;
}
.finished__not {
  background-color: tomato;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
  <div v-for="exercise in exercises" :key="exercise.id">
   <span> {{ exercise.name }} </span>
    <div v-for="set in exercise.sets" :key="set">
      <div @click="completeSet(exercise.id, set)"  :> {{ set }} <span>
      <span v-if="isFinished(exercise.id, set)">finished</div>
    </div>
  </div>
  {{finishedSets}}
</div>

  • Related