Home > Net >  v-for inside v-for issue
v-for inside v-for issue

Time:12-17

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" >
  <p >{{ group.title }}</p>
  <div v-if="group.links">
    <a v-for="(link, u) in group.links" :key="u" :href="link.src" > {{ 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 >{{ 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>

CodePudding user response:

You should avoid using indexes as keys in your v-for loop. The keys need to be unique for every element. By using index you have probably 2 elements with index 0 as a key. Vue cannot keep track of changes in the DOM that way. It is getting even worse if you edit the array and items in the array get another index.

So, you can use a unique value for the key, maybe an id or link.url and item.title in your code.

See docs: https://vuejs.org/guide/essentials/list.html#maintaining-state-with-key

CodePudding user response:

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 >{{ group.title }}</p>
  <div v-if="group.links">
    <a v-for="link in group.links" :key="link.src" :href="link.src" > {{ 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 >{{ item.title }}</v-expansion-panel-header>
      <v-expansion-panel-content >
         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>

  • Related