'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