In Vuetify’s v-expansion-panels component, there’s a significant difference in how v-model tracks selected panels between versions 2 and 3. Let’s explore this behavior:
Vuetify 2 Behavior
In Vuetify 2, v-model only tracks by index regardless of what you set as the
1 | :key |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 <!-- v-model ONLY tracks by index regardless of :key -->
<v-expansion-panels v-model="selectedIndex">
<v-expansion-panel
v-for="(item, index) in items"
:key="item.value" <!-- This doesn't affect v-model behavior -->
>
<v-expansion-panel-header>
<div :class="{ 'active': selectedIndex === index }">
{{ item.text }}
</div>
</v-expansion-panel-header>
</v-expansion-panel>
</v-expansion-panels>
<script>
export default {
data: () => ({
selectedIndex: null // Will be 0, 1, 2, etc.
}),
computed: {
selectedValue() {
return this.items[selectedIndex]?.value;
}
}
}
</script>
The Gotcha
- The v-model tracks by index (0, 1, 2, etc.)
- The
binding has no effect on tracking1:key
- Need a computed property to get the actual value
Vuetify 3 Behavior
Vuetify 3 introduces value tracking through the
1 | :value |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 <!-- Can track by actual value using :value prop -->
<v-expansion-panels v-model="selected">
<v-expansion-panel
v-for="item in items"
:key="item.id"
:value="item.id" <!-- v-model will track this value -->
>
<v-expansion-panel-header>
{{ item.text }}
</v-expansion-panel-header>
</v-expansion-panel>
</v-expansion-panels>
<script>
export default {
data: () => ({
selected: null // Will be actual item.id value
})
}
</script>
Improvements
- Can track by custom values using
prop1:value
- Directly stores the selected value in v-model
- No need for computed properties to get actual values
- More intuitive value tracking
Best Practices
Vuetify 2
- Name variables to clearly indicate index tracking (e.g., selectedIndex)
- Use computed properties to get actual values
- Be explicit about index-based tracking in code comments
Vuetify 3
- Can use semantic names for v-model variables
- Utilize the
prop for direct value tracking1:value
- More straightforward implementation
This change in Vuetify 3 represents a significant improvement in the developer experience, making the component behavior more intuitive and requiring less boilerplate code.