Solved -- solution at bottom of post
I'm experiencing a problem in Vue2 where I'm trying to control a v-if
& v-else
based on an @click
event inside a v-for
loop, but the v-if
is not changing dynamically each click like I would expect.
Here is roughly the code that is failing (note: people
comes from a store file and is fully loaded when used):
<div v-for="(person, index) in people" :key="index">
<div @click="detailsOpened(index)">
<PersonIcon v-if="showDetails(index)" />
<PersonIcon2 v-else />
</div>
</div>
import {
each
} from 'lodash-es'
data(): {
return {
personMap: []
}
}
beforeMount() {
this.personMap = each(people, () => false)
}
methods: {
showDetails(index: number): boolean {
return this.personMap[index] === true
}
detailsOpened(index: number): boolean {
return this.personMap[index] = !this.personMap[index]
}
}
I've done console.log
print outs and detailsOpened
seems to work correctly. The boolean value keyed at each relevant index changes when the icon is clicked so that isn't the problem. It seems the v-if
only runs when the page first renders and it doesn't update dynamically when the personMap
values change. console.log
's confirm that the showDetails
method only runs at the beginning of the page loading, based on the size of the people
array. I'm not sure what is causing this and would appreciate any help in the right direction!
Edit: Solution
I had tried the top answer's advice but get hit with the console error, "Error: [vuex] do not mutate vuex store state outside mutation handlers.". I moved these methods and data to a Pinia store file and explictly called "Vue.set"/"this.$set" in the store's setter and still got the the same error. What ultimately solved my problem was 1) Moving data and methods to a Pinia store file. 2) Using using Vue.set
on the detailsOpened
method inside the store file. 3) Using lodash's cloneDeep
on people
when this.personMap
was initialized.