Search code examples
javascriptvue.jsvuetifyjs3

v-for inside v-for issue


I would like to ask if someone see the problem in my code. Everything render ok, no problem with the render, the issue is that every time I click in one panel content all the panel-content of every group with the same index expand or collapse and not only the one that I clicked. Any idea?? Thanks a lot.

<div v-for="(group, i) in groups" :key="i" class="pb-4">
  <p class="text-h5 primary text-center white--text">{{ group.title }}</p>
  <div v-if="group.links">
    <a v-for="(link, u) in group.links" :key="u" :href="link.src" class="black--text"> {{ link.title }}</a>
  </div>
  <v-expansion-panels v-model="activesPanels" multiple accordion dense flat>
    <v-expansion-panel v-for="(item, v) in group.fact" v-show="shouldRender(v)" :key="v">
      <v-expansion-panel-header class="px-0">{{ item.title }}</v-expansion-panel-header>
      <v-expansion-panel-content>
         <type :fact="item" :models="models" />
      </v-expansion-panel-content>
    </v-expansion-panel>
  </v-expansion-panels>
</div>

Solution

  • The reason for this issue is that you are using the same v-model variable activesPanels for every group. The activesPanels should belong to each group to maintain their opening and closing state individually.

    Also, use the unique properties for template keys to avoid errors i.e, "Duplicate keys detected".

    Here is the working demo-

    <!DOCTYPE html>
    <html>
      <head>
        <link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
      </head>
      <body>
        <div id="app">
          <v-app id="inspire">
        <div v-for="(group, i) in groups" :key="i">
      <p class="primary text-center white--text">{{ group.title }}</p>
      <div v-if="group.links">
        <a v-for="link in group.links" :key="link.src" :href="link.src" class="black--text"> {{ link.title }}</a>
      </div>
      <v-expansion-panels v-model="group.activesPanels" multiple accordion dense flat>
        <v-expansion-panel v-for="item in group.fact" :key="item.title">
          <v-expansion-panel-header class="pa-0">{{ item.title }}</v-expansion-panel-header>
          <v-expansion-panel-content class="pa-0">
             Hello
          </v-expansion-panel-content>
        </v-expansion-panel>
      </v-expansion-panels>
    </div>
      </v-app>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
        <script>
          new Vue({
            el: '#app',
            data () {
          return {
            groups: [
            {
              title: "group1",
              activesPanels: [],
              fact: [
                {
                  title: 'fact1'
                }
              ],
              links:[
                {
                  src: "https://google.com",
                  title: "Hello"
                },
                {
                  src: "https://twitter.com",
                  title: "Hello"
                }
              ]
            },
            {
              title: "group2",
              activesPanels: [],
              fact: [
                {
                  title: 'fact2'
                }
              ],
              links:[
                {
                  src: "https://www.shorturl.at/",
                  title: "Hello"
                },
                {
                  src: "https://www.npmjs.com/package/vuex-map-fields",
                  title: "Hello"
                }
              ]
            }
          ]
          }
          },
            vuetify: new Vuetify(),
          })
        </script>
      </body>
    </html>