valtro05
valtro05

Reputation: 81

Remove Class for All Items and Add Class to Clicked Itemin Vue.js

So, I know how to do this in just vanilla JS, where if I have a list of things and want one item to be active at a time, I'd remove the class from all of the items listed and add it to the one that was clicked. Unfortunately, I cannot seem to figure it out in Vue.js, as I am still learning it. I am wanting to trigger a variable named 'activeComp' as true just for the clicked element, and make it false for all the other clicked elements, so only one item is active at a time. As of right now, it will allow me to select one at a time, but the class remains on the others. Here is my code:

<div v-if="companions.length > 0" v-for="companion in companions">

  <comp-item :companionData="companion"></comp-item>

</div>



<template>

  <div class='companion-item' @click="toggleActive" :class="{ active: activeComp }">
    <h3>{{ companionData.name }} <span class='desc'>({{ companionData.desc }})</span></h3>
  </div>

</template>

<script>
  export default {
    props: ['companionData'],
    data() {
      return {
        activeComp: false
      };
    },
    methods: {
      toggleActive() {
        this.activeComp = !this.activeComp;
      }
    }
  }
</script>

Any help on this is much appreciated.

Upvotes: 0

Views: 6037

Answers (1)

ittus
ittus

Reputation: 22393

Since there is only 1 active item at a moment, you should keep track of current active item in parent component:

<div 
  v-if="companions.length > 0" 
  v-for="(companion, index) in companions" 
  :key="index">
  <comp-item :companionData="companion" 
             :isActive="activeIndex === index" 
             @onToggle="onToggle(index)">
  </comp-item>
</div>

<script>
  ...
    data() {
      return {
        activeIndex: null
      };
    },
    methods: {
      onToggle(index) {
        if (this.activeIndex === index) {
          this.activeIndex = null;
        } else {
          this.activeIndex = index;
        }
      }
    }
    ...
</script>

Then in child component, you can emit click event to parent:

<template>

  <div class='companion-item' @click="toggleActive" :class="{ active: isActive }">
    <h3>{{ companionData.name }} <span class='desc'>({{ companionData.desc }})</span></h3>
  </div>

</template>

<script>
  export default {
    props: ['companionData', 'isActive'],
    data() {
      return {
      };
    },
    methods: {
      toggleActive() {
        this.$emit('onToggle')
      }
    }
  }
</script>

When user clicks on an item, event will be emit to parent and handled in onToggle method.

Upvotes: 2

Related Questions