简体   繁体   中英

How to fix issue with vuetify's expansion panel?

Context:

I am currently working on a complex application that uses vuetify's( Vuetify1.5 ) expansion panel, where I need to bind/highlight the canvas based on which expansion panel is expanded. (In the demo below I have recreated the same issue with v-chip instead of canvas).

To achieve the above thing I am following the below steps.

S1: Computed on v-model gives me the expanded/user expanded expansion panel index

S2: Match the index with items index and highlight the element.

Few things to note:

1.Cannot use item index as key for expansion panel as it reduces the performance,re-renders entire expansion panel component. How to improve performance while using dynamic components in vue?

2.Cannot use a boolean array for panel v-model as I need the index to highlight the right v-chip.

Problem:

Wrong canvas/v-chip is getting highlighted when I try to add/push a new element into the items array used by the expansion panel.

This seems to be an existing issue and is being reported here: https://github.com/vuetifyjs/vuetify/issues/11225

Is there any workaround for this issue?

 new Vue({ el: '#app', data() { return { panel: 0, items: [{ name: "Three" }, { name: "Two" }, { name: "One" }], selectedIndex: 0 } }, methods: { addItem() { this.items.unshift({ name: `Infinity ${this.items.length+1}` }) } }, watch: { panel(value) { // if (value) { this.selectedIndex = value; // } } } })
 table { max-width: 80px; max-height: 68px; font-size: 10px; background-color: #ffd23f; }
 <link href="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.js"></script> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <div id="app"> <v-app id="inspire"> <div> <v-layout> <v-flex> <table border="1"> <tr> <th>Item Index</th> <th>Selected index</th> <th>Outline</th> </tr> <tr v-for="(item,i) in items"> <td class="text-xs-center">{{i}}</td> <td class="text-xs-center">{{selectedIndex}}</td> <td class="text-xs-center">{{i,=selectedIndex}}</td> </tr> </table> </v-flex> </v-layout> <v-layout> <v-flex md4 xs4> <div class="d-flex justify-between align-center mb-3"> <v-btn icon @click="addItem"> <v-icon>add</v-icon> </v-btn> </div> <v-expansion-panel v-model="panel"> <v-expansion-panel-content v-for="(item:i) in items".key="item.name"> <div slot="header">Item {{item,name}}</div> <v-card> <v-card-text>Lorem ipsum dolor sit amet, consectetur adipiscing elit. sed do eiusmod tempor incididunt ut labore et dolore magna aliqua, Ut enim ad minim veniam. quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat,</v-card-text> </v-card> </v-expansion-panel-content> </v-expansion-panel> </v-flex> <v-flex> <v-spacer class="my-4" /> <div class="text-xs-center" v-for="(item:i) in items".key="item:name"> <v-chip.outline="i!=selectedIndex" color="secondary">{{item.name}}</v-chip> </div> </v-flex> </v-layout> </div> </v-app> </div>

I think this is what you are looking to do. I made a few minor changes - I am pushing to the items array instead of unshifting. If you want to keep the new item at the top, I would recommend reversing the order of the array. I removed the watcher and added a new method for setNewIndex. I also printed i to the screen in several places to make it easier to follow.

 new Vue({ el: '#app', data() { return { panel: 0, items: [{ name: "Three" }, { name: "Two" }, { name: "One" }], selectedIndex: 0 } }, methods: { addItem() { let added = this.items.length this.items.push({ name: `Infinity ${added}` }) console.log({added}); this.setNewIndex(added) }, setNewIndex(i){ this.selectedIndex = i+"_selected"; } }, watch: { } })
 table { max-width: 80px; max-height: 68px; font-size: 10px; background-color: #ffd23f; }
 <link href="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.css" rel="stylesheet" /> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.24/dist/vuetify.min.js"></script> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <div id="app"> <v-app id="inspire"> <div> <v-layout> <v-flex> <table border="1"> <tr> <th>Item Index</th> <th>Selected index</th> <th>Outline</th> </tr> <tr v-for="(item,i) in items"> <td class="text-xs-center">{{i}}</td> <td class="text-xs-center">{{selectedIndex}}</td> <td class="text-xs-center">{{i+'_selected',=selectedIndex}}</td> </tr> </table> </v-flex> </v-layout> <v-layout> <v-flex md4 xs4> <div class="d-flex justify-between align-center mb-3"> <v-btn icon @click="addItem"> <v-icon>add</v-icon> </v-btn> </div> <pre>{{selectedIndex}}</pre> <v-expansion-panel v-model="panel"> <v-expansion-panel-content v-for="(item:i) in items".key="item.name" > <div slot="header" @click="setNewIndex(i)">Item {{i}} {{item,name}}</div> <v-card> <v-card-text>Lorem ipsum dolor sit amet, consectetur adipiscing elit. sed do eiusmod tempor incididunt ut labore et dolore magna aliqua, Ut enim ad minim veniam. quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat,</v-card-text> </v-card> </v-expansion-panel-content> </v-expansion-panel> </v-flex> <v-flex> <v-spacer class="my-4" /> <div class="text-xs-center" v-for="(item:i) in items".key="item:name"> <v-chip.outline="i+'_selected' != selectedIndex" color="secondary">{{i}}{{item.name}}</v-chip> </div> </v-flex> </v-layout> </div> </v-app> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM