Search code examples
javascriptloopsvue.jsbind

How to change color after clicking a loop?


I have loop as below:

data: {
  show: false
}
.test {
  hight: 10px;
  background-color: red;
}

.test2 {
  hight: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div v-for="value in data" :key="value.id">
  <div class="test" v-bind:class="{ test2: show }" v-on:click="show = !show">
  </div>
</div>

Now if I click any div, it will be changed all the divs's height from 15 to 10 or 10 to 15.

However, I want to change the only the div that I clicked. How can I do this?


Solution

  • You need to add show variable for each element:

    new Vue({
      el: "#app",
      data: {
      	show: [],
        items: []
      },
      created() {
        fakeFetch().then((items) => {
           this.items = items;
           this.show = this.items.map(() => false);
        });
      },
      methods: {
      	isShown(i) {
        	return this.show[i]
        },
        changeShow(i) {
        	Vue.set(this.show, i, !this.show[i]);
        }
      }
    })
    
    function fakeFetch() {
      return new Promise((resolve, reject) => {
         let count = Math.floor(Math.random() * 20) + 1;
         let result = [];
         for (let i = 0; i < count; i++) {
           result.push({ text: Math.random() });
         }
         resolve(result);
      })
    }
    .test {
      height:10px;
      background-color: red;
      margin: 10px;
    }
    .test2 {
      height: 35px;
     }
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    <div id="app">
      <h2>Items:</h2>
      <div 
      class="test" 
      :class="{ test2: isShown(index) }"
      @click="changeShow(index)" 
      v-for="(item,index) in items" :key="index">
      </div>
    </div>

    P.S. To avoid this routine with show array you can define each element as component and switch visibility inside it with single variable show .