javascriptvue.jsnuxt.jsnuxtjs2

nuxtjs toggle individual items generated by v-for loop


I want to create a simple accordion like structure but somehow I can't manage to toggle individual elements:

<div v-for="qa, j in group.questions_answers" :key="j">
  <div class="question" @click="toggle()" > <!-- use index here? -->
    <span v-if="itemOpen" class="font-iconmoon icon-accordion-up"><span/>
    <span v-else class="font-iconmoon icon-accordion-down"><span/>
    <span class="q-text" v-html="qa.question"><span/>
  </div>
  <div v-if="itemOpen" class="answer" v-html="qa.answer"></div>
</div>

How would I go about toggling indiviual question/answer blocks? Do I need to use refs?

Currently I can toggle all elements ...

export default {
  data() {
    return {
      itemOpen: true
    }
  },
  methods: {
    toggle() { // index
      this.itemOpen = !this.itemOpen
    }
  }
}

I could draft up a Q/A component and then do toggle inside of each Component but I believe that is an overkill for this.

UPDATE I am dealing with following data structure:

{
    "intro_text": "intro text",
    "questions_groups": [
        {
            "group_heading": "heading",
            "questions_answers": [
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {...}
            ]
        },
        {
            "group_heading": "heading 1",
            "questions_answers": [
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {...}
        },
        {
            "group_heading": "heading 2",
            "questions_answers": [
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                },
                {
                    "question": "Question",
                    "answer": "Answer"
                }
                {...}
            ]
        }
    ]
}

Solution

  • Since I did not have an id and done field on the individual question/answer object and I would have needed to loop through several q/a groups, It was easier and more performant to create a sub component in that case to target the individual q/a rows for toggle:

    <template>
      <div>
        <slot-main-heading>{{$t('faq.h1')}}</slot-main-heading>
        <div v-html="introText"></div>
        <div v-for="(group, i) in questionsGroups" :key="i">
          <slot-htwo-heading>{{group.group_heading}}</slot-htwo-heading>
          <template v-for="(qa, j) in group.questions_answers">
            <cms-accordion-row :qaData="qa" :key="j"/>
          </template>
        </div>
      </div>
    </template>
    

    cmsAccordionRow.vue

    <template>
    <div>
      <div class="question" @click="toggle()">
          <span v-if="itemOpen" class="font-iconmoon icon-accordion-up" ></span>
          <span v-else class="font-iconmoon icon-accordion-down" ></span>
          <span class="q-text" v-html="qaData.question" ></span>
      </div>
      <div v-if="itemOpen" class="answer" v-html="qaData.answer"></div>
    </div>
    </template>
    
    <script>
    export default {
      props: {
        qaData: {
          type: Object,
          required: true
        }
      },
      data() {
        return {
          itemOpen: true
        }
      },
      methods: {
        toggle() {
          this.itemOpen = !this.itemOpen
        }
      }
    }
    </script>