Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

596
Visualizações
In Vue JS, how do I add a class to an element inside my v-for loop when clicked on, without it being added to each looped element?

Hope the question made some sense. I'm using Vue JS and I have few elements being looped using v-for. Inside each block of elements being looped, is a button along with a div. In this case my loop runs three times. That means I get three buttons in each looped block of code, along with those three div's.

When I click on one of the three buttons I would like for the div in that block to receive a class dynamically. However, as it stands, when I click on one of the three buttons, the class is being added, but it is being added to all three looped div elements inside the loop.

How can I get the current looped div to only receive the specific class when the related button is clicked on, without the other two div's from the loop receiving it also?

Here is my code so far with what I have tried myself:

<template>
    <div v-for="(todo, index) in todos" :key="index" class="relative">
        <button @click="showDiv">
            show div
        </button>
        <div :class="appear" class="absolute bg-red-500">
            <p>{{ todo.text }}</p>
        </div>
    </div>
</template>

<script>
    import {defineComponent} from 'vue'
    export default defineComponent({
        data() {
            return {
                appear: 'left-0',
                todos: [
                    { text: 'Learn Laravel' },
                    { text: 'Learn Vue JS' },
                    { text: 'Learn Tailwind CSS' },
                ]
            }
        },
        methods: {
            showDiv() {
                this.appear = 'left-2/4';
            }
        }
    })
</script>
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

This is happening because you have all of your code running at the same "level" (or scope to be more technical), thus the DOM "thinks" all of the elements are supposed to get the class added to it. You can solve this problem easily by simply creating a new component for repetitive bits of code (like when you need a for loop) and by making use of Vue's slots (https://vuejs.org/v2/guide/components-slots.html) feature.

// corresponding example JS file or section (depending on your setup) for TodoListItem
export default {
  name: 'TodoListItem',
  props: {
    todo: { type: Object, requried: true } 
  },
  data() {
    return { 
      isClicked: false 
    }
  },
  methods: {
    toggleIsClicked() {
      this.isClicked = !this.isClicked;
    },
  },
};
<!-- index.html -->
<todo-list>
  <todo-list-item
    v-for="(todo, index) in todos"
    :key="index"
    :todo="todo"
  ></todo-list-item>
</todo-list>

<!-- TodoList.vue -->
<template>
  <div class="todo-container">
    <slot></slot>
  </div>
</template>

<!-- TodoListItem.vue -->
<!-- Don't forget to set your props in the corresponding component JS file or else your TodoListItem.vue won't know about the todo object you are passing down to it. -->
<!-- You will also need to move your @click handler here too in the methods section -->
<template>
  <div class="relative">
    <button @click="showDiv">show div</button>
    <div :class="appear" class="absolute bg-red-500">
      <p>{{ todo.text }}</p>
    </div>
  </div>
</template>

I hope this helps my friend!

over 4 years ago · Santiago Trujillo Relatório

0

The reason is that you are using one variable appear to manage the state of all the buttons, instead you can maintain seperate booleans called visible for each of the items

Check the below working example

var app = new Vue({
        el: "#app",
        data() {
            return {
                appear: 'left-0',
                
                /*** Change added to below array ***/
                
                todos: [
                    { text: 'Learn Laravel', visible: false },
                    { text: 'Learn Vue JS', visible: false },
                    { text: 'Learn Tailwind CSS', visible: false },
                ]
            }
        },
        /** Changes added below **/
        computed: {
         getButtonText() {
          return ind => {
           return this.todos[ind].visible ? 'hide div': 'show div';
          }
         },
         getClass() {
           return ind => {
             return this.todos[ind].visible ? 'left-2/4': 'absolute bg-red-500';
           }
         }
        },
        methods: {
            showDiv(index) {
                this.todos[index].visible = !this.todos[index].visible; // Change added
            }
        }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
    <div v-for="(todo, index) in todos" :key="index" class="relative">
        <button @click="showDiv(index)">
           {{getButtonText(index)}} <!-- Change added -->
        </button>
        <div :class="getClass(index)"> <!-- Change added -->
            <p>{{ todo.text }}</p>
        </div>
    </div>
</div>

over 4 years ago · Santiago Trujillo Relatório

0

add a boolean field in your array and use that field as a condition for the dynamic class e.g

                { text: 'Learn Laravel', isLeft: false },
                { text: 'Learn Vue JS', isLeft: false },
                { text: 'Learn Tailwind CSS', isLeft: false },

Now on click, just toggle the isLeft field and use it as a condition to dynamic class

<div v-for="(todo, index) in todos" :key="index" class="relative">
    <button @click="todo.isLeft = !todo.isLeft">
        show div
    </button>
    <div :class="{'left-2/4': todo.isLeft}" class="absolute bg-red-500">
        <p>{{ todo.text }}</p>
    </div>
</div>                
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda