Search code examples
javascriptvue.jsvuejs3vue-composition-apiv-for

Vue3 toggle element in v-for loop


I am looping through an array on v-for loop in vue 3. Is there a way to toggle the v-show of a paragraph by clicking on the Heading element. Below is my code :

<div class="defs">
<ul v-for="(d, index) in definitions"
              :key="'d' + index">
   <li>
  <div class="project" >
    <div @click="showDetails" class="actions">
      <h3>{{ d.title }}</h3>
      <div class="icons">
         <span  class="material-icons" ><i class="fas fa-trash-alt"></i></span> 
  <span class="material-icons" ><i class="fas fa-pencil-alt"></i></span> 
      </div>
    </div>
    <div v-if="show" class="details">
      <p>{{d.explanation}}</p>
    </div>
  </div>
  </li>
</ul>
</div>



<script>
import { ref } from "vue";
import { projectDatabase} from '../../firebase/config'

export default {
  props: ['id'],
  setup(props){

  const show = ref(false);

  
  
  const showDetails = () =>{
    show.value = !show.value
  }

      return {
      definitions, props, show, showDetails, 
    }
  }
}
</script>

I know we cant use this in composition API. so how can we solve the toggle issue ?


Solution

  • Try like following snippet, here is the codesandbox with composition API

    const demo = {
      data() {
        return {
          definitions: [
            { title: "aaa", explanation: "aaa" },
            { title: "bbb", explanation: "bbb" },
            { title: "ccc", explanation: "ccc" },
          ],
          show: null
        }
      },
      methods: {
        showDetails(idx) {
          this.show === idx ? (this.show = null) : (this.show = idx);
        }
      },
      // same code with coposition API
      /*import { ref } from "vue";
      import { projectDatabase} from '../../firebase/config'
      setup() {
        const show = ref(null);
        const definitions = ref([
          { title: "aaa", explanation: "aaa" },
          { title: "bbb", explanation: "bbb" },
          { title: "ccc", explanation: "ccc" },
        ]);
    
        const showDetails = (idx) => {
          show.value === idx ? (show.value = null) : (show.value = idx);
        };
    
        return { definitions, show, showDetails }
      },*/
    };
    Vue.createApp(demo).mount("#demo");
    <script src="https://unpkg.com/vue@next"></script>
    <link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
    <div id="demo">
      <div class="defs">
        <ul>
          <li v-for="(d, index) in definitions" :key="index">
            <div class="project">
              <div @click="showDetails(index)" class="actions">
                <h3>{{ d.title }}</h3>
                <div class="icons">
                  <span class="material-icons"
                    ><i class="fas fa-trash-alt"></i
                  ></span>
                  <span class="material-icons"
                    ><i class="fas fa-pencil-alt"></i
                  ></span>
                </div>
              </div>
              <div v-if="show === index" class="details">
                <p>{{ d.explanation }}</p>
              </div>
            </div>
          </li>
        </ul>
      </div>
    </div>