'Manipulating v-list-item-group model with object instead of list index
I am using v-list-item-group to display a list of dynamic items (entities that can be created/deleted), of which can be selected to display more information about the selected item.
Up until this point, I have simply been using the model of v-list-item-group to determine which item has been selected.
<template>
<v-list>
<v-list-item-group v-model="listSelection">
<v-list-item v-for="(item, index) in items" :key="index">
</v-list-item>
</v-list-item-group>
</v-list>
</template>
<script>
export default {
props: {
value: Object
},
computed: {
items: function() {
return this.$store.state.items // Collection of entities from a server
},
listSelection: {
get: function() {
return this.items.indexOf(this.value)
},
set: function(newVal) {
this.$emit('input', this.items[newVal])
}
}
},
}
</script>
This approach works fine with the initial data set, as the first element in the list is the first object in items
, etc. However, if I add an entity in the middle, or remove something, or simply cause one of the items to shift to a different position in the list, the index to item position becomes invalid. Essentially if the list adds a new element, regardless of its position, its value (when selected in the group) is the next highest unused value. For example:
let fruits = ['apple', 'carrot']
<v-list-item>
for apple will have a value 0, and <v-list-item>
for carrot will have a value 1.
fruits.splice(1, 0, "banana")
<v-list-item>
for apple will have a value 0, <v-list-item>
for banana will have a value 2, and <v-list-item>
for carrot will have a value 1.
I've done a bunch of playing around with v-model and value in v-list-item-group
, but have not figured out how to avoid this problem. I would be fine with adding an @click
on my items, and having the items set a value
, rather than computing based on the list, but I would like the list selection to be maintained based on the value
.
As best as i've read, the documentation indicates that selection in lists should be handled using a v-list-item-group, but the component doesn't seem to support dynamic lists too well.
Solution 1:[1]
Upon additional inspection of the documentation, <v-list-item>
supports a value prop, allowing <v-list-item-group
to use a dictated value instead of the item index.
So the solution was to simply specify the items id as the value for each item, and then use the id as a means of managing the item group model.
<template>
<v-list>
<v-list-item-group v-model="listSelection">
<v-list-item v-for="(item, index) in items" :key="index" :value="item.id">
</v-list-item>
</v-list-item-group>
</v-list>
</template>
<script>
export default {
props: {
value: Object
},
computed: {
items: function() {
return this.$store.state.items; // Collection of entities from a server
},
listSelection: {
get: function() {
return this.value.id;
},
set: function(newVal) {
this.$emit('input', this.items.find(item => item.id === newVal));
}
}
},
}
</script>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Lukasz Madon |