Home » vue » Is there a way to pass v-model to function that toggles a specific accordion?

Is there a way to pass v-model to function that toggles a specific accordion?

Posted by: admin November 26, 2021 Leave a comment

Questions:

I’m wondering if this can be done in my scenario. I have two vue / element ui accordions on a page and I have setup an "open all, close all" button for the accordions. How would I go about giving each accordion a unique ID and pass that ID to the function that toggles the accordions? Or is there a way to share the same v-model with some sort of other unique identifier so I can reuse the function on each accordion but only "open all, close all" of that given accordion section.

https://codepen.io/mDDDD/pen/gOwxQxz

html:

<div id="app">
<template>
  <div class="toggle-block">
     <button @click="togglePanels()" class="toggle">
            {{ activeNames.length === 4 ? "Close" : "Open" }} all
          </button>
    </div>
<el-collapse v-model="activeNames">
    <el-collapse-item title="Panel 1" name="1">
        <div class="collapse-content">
            <p>Content 1</p>
        </div>
    </el-collapse-item>
    <el-collapse-item title="Panel 2" name="2">
        <div class="collapse-content">
            <p>Content 2</p>
        </div>
    </el-collapse-item>
    <el-collapse-item title="Panel 3" name="3">
        <div class="collapse-content">
            <p>Content 3</p>
        </div>
    </el-collapse-item>
    <el-collapse-item title="Panel 4" name="4">
        <div class="collapse-content">
            <p>content 4</p>
        </div>
    </el-collapse-item>
</el-collapse>

  <div class="spacer"></div>
  
  
    <div class="toggle-block">
     <button @click="togglePanels()" class="toggle">
            {{ activeNames.length === 4 ? "Close" : "Open" }} all
          </button>
    </div>

<el-collapse v-model="activeNames">
    <el-collapse-item title="Panel 1" name="1">
        <div class="collapse-content">
            <p>Content 1</p>
        </div>
    </el-collapse-item>
    <el-collapse-item title="Panel 2" name="2">
        <div class="collapse-content">
            <p>Content 2</p>
        </div>
    </el-collapse-item>
    <el-collapse-item title="Panel 3" name="3">
        <div class="collapse-content">
            <p>Content 3</p>
        </div>
    </el-collapse-item>
    <el-collapse-item title="panel 4" name="4">
        <div class="collapse-content">
            <p>content 4</p>
        </div>
    </el-collapse-item>
</el-collapse>
  </template>
</div>

js:

var Collapse = {
      data() {
        return {
         activeNames: []
        }
      },
  methods: {
    togglePanels: function() {
      if (this.activeNames.length <= 3) {
        this.activeNames.push("1", "2", "3", "4");
      } else if ((this.activeNames.length = 4)) {
        this.activeNames = [];
      }
    }
  }
    }
var col = Vue.extend(Collapse)
new col().$mount('#app')
Answers:

Arguably the simplest way would be to wrap a single accordion as a component. This will allow it to manage its own state internally and you can have as many as you want without them interfering with each other.

See it here: https://codepen.io/andrei-gheorghiu/pen/QWKqbwv

data: () => ({
  accordions: 2
})

<accordion v-for="(accordion, key) in accordions" :key="key" />

Note I’ve also made panels a prop, so you can inject them from the parent component. The opening/closing logic is no longer hard-coded to 4 panels only, they can be as many as you want.