In the following code:
const App = {
template: '#app-template',
data: () => ({
selected: [],
items: Array.from({length: 50}, (x, i) => i+1).map(i => ({
id: i ,
name: `Item ${i}`,
subtitle: `Subtitle ${i}`
}))
}),
computed: {
parsedItems() {
this.selected;
return this.items.map(item => ({
someValue: 3,
...item
}));
}
}
}
new Vue({
vuetify: new Vuetify(),
render: h => h(App)
}).$mount('#app')
<script type="text/x-template" id="app-template">
<v-app>
{{selected}}
<v-container>
<v-virtual-scroll
:items="parsedItems"
:item-height="65"
height="500"
>
<template v-slot="{ item, index }">
<v-list-item-group
v-model="selected"
multiple
>
<v-list-item :key="item.id" :value="item">
<v-list-item-action>
<v-checkbox
:input-value="selected.includes(item.id)"
color="primary"
/>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
Index: {{ index }} {{ item.name }}
</v-list-item-title>
<v-list-item-subtitle>
{{ item.subtitle }}
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</template>
</v-virtual-scroll>
</v-container>
</v-app>
</script>
<div id="app"></div>
When either of the checkboxes i checked or unchecked - the selected
v-model always adds up another instance though it previously contains one already.
Removing this.selected;
(line 16 in the Codepen below) fixes the issue.
I suspect that this.selected
is somehow dereferences its own values and then can't validate the appearance of previously selected items.
Here's a Codepen with the issue at hand: https://codepen.io/MichaelKatz/pen/vYXXdgb
In my real-world scenario, I need to filter and manipulate items within the list, according to previously made selections (i.e remove / re-add items).
I do it by using a computed item
property which derives its content from a previously selected items, from the selected
v-model and my current solution will require me to JSON.stringify
all of my objects, essentially making them value-based strings to keep things in check.
It seems like accessing a v-model while filtering the items it refers to, creates a de-reference of the objects within it.
The best solution I could come up with was adding an additional computed property which will contain the logic involving this.selected
.
It has indeed solved the issue for me.
computed: {
parsedItems() {
return this.items.map(item => ({
someValue: 3,
...item
}));
},
filteredItems() { // adding another computed property while using this.selected
this.selected;
return this.parsedItems;
}
}
}