Search code examples
javascriptcsslistvue.jshtml-framework-7

Apply styles to specific v-for element


I'm making a simple todo list app, and wondering on how to apply styles on only specific dynamic v-for elements.

<f7-list-item v-for="(listItem, index) in activeList.listItems" :key="index" :class="(checked) ? 'checked':'not-checked'">
 {{ index+1 }}. {{ listItem }}
  <span @click="checkTaskDone(index)">
    <i class="f7-icons" id="check-task-btn">check_round</i>
  </span>
</f7-list-item>
export default {
 data() {
  return {
   checked: false
  }
 },
 methods: {
  checkTaskDone(item) {
   if (this.checked == false) {
    this.checked = true;
   } else if (this.checked == true) {
    this.checked = false;
   }
  }
 }
}
.checked {
 text-decoration: line-through;
 color: #444;
}

With this code it adds the class to every single v-for list element regardless of which one is clicked, as expected. I'm wondering what's the best approach to deal with this. I've experimented with making a prop from the index and trying to target that to apply the styles but I couldn't make it work.

Thanks in advance!


Solution

  • Typically you want to have a "done" or "checked" flag on the individual to-do items, something like:

    const todoList = [
      {
        name: 'Grab some food',
        done: false
      },
      {
        name: 'Start coding',
        done: false
      }
    ];
    

    And in Vue.js, you could do the class toggling with v-bind:class rather than ternary operator:

    export default {
      data() {
        return {
          //checked: false,
          
          activeList: {
            listItems: [
              {
                name: 'Grab some food',
                done: false
              },
              {
                name: 'Start coding',
                done: false
              }
            ]  
          }
        }
      },
      methods: {
        checkTaskDone(item) {
          //if (this.checked == false) {
          //  this.checked = true;
          //} 
          //else if (this.checked == true) {
          //  this.checked = false;
          //}
          
          // Check/uncheck
          item.done = !item.done;
        }
      }
    }
    
    <f7-list-item 
      v-for="(listItem, index) in activeList.listItems" 
      :key="index"
      :class="{ 'checked': listItem.done }">
      
     {{ index + 1 }}. {{ listItem }}
     
      <span @click="checkTaskDone(listItem)">
        <i class="f7-icons" :id="`check-task-btn${index}`">check_round</i>
      </span>
    </f7-list-item>
    

    BTW, I'm appending an index on the individual i.f7-icons elements because ID should be unique, otherwise please use class instead.