Say I have this data retrieved from my store:
let itemsData=[
{id:1,data:[...]},
{id:2,data:[...]},
{id:3,data:[...]}
]
I need to be able to produce an array from this data which looks something like this:
let itemsSelected=[
{id:1,selected:false},
{id:2,selected:false},
{id:3,selected:false}
]
And then I need to have this array, itemsSelected
, accessible to determine the state of multiple different components in the template, for example:
<div v-for="item in itemsSelected" :key="item.id" :></div>
I originally thought to use a computed property, but I need to be able to dynamically update the selected
value of items in itemsSelected. However, I also want the array to be constructed based on data in the store, and it should add/remove items from itemsSelected
whenever itemsData
changes. How can I achieve these things together?
CodePudding user response:
You could use a watcher to update itemSelected
based on itemsData
. The following example uses Array.prototype.reduce
to create a new map of item IDs to a shallow copy of the original array item plus a selected
property:
import { watchEffect, ref, reactive } from 'vue'
let itemsData = reactive([
{ id: 1, data: [newData()] },
{ id: 2, data: [newData()] },
{ id: 3, data: [newData()] },
])
let itemsSelected = ref({})
watchEffect(() => {
const selections = itemsSelected.value
itemsSelected.value = itemsData.reduce((p, c) => {
p[c.id] = {
...c,
selected: selections[c.id]?.selected ?? false,
}
return p
}, {})
})
This allows itemsSelected
to still be editable, enabling modification of the selected
properties in itemsSelected
without affecting itemsData
.