I am experiencing a few issues regarding reactivity in my application.
I have a Vuex store where I have an object 'songs' containing 'song' objects where the key is their id. For each song object within, I have various properties, with the one in question being 'playing' a boolean value.
e.g.
songs = {
2: {playing: false},
7: {playing: true)
}
Within my application I have a list, using v-for for all these songs with a button that toggles the playing property of the song. When the button is pressed I dispatch the action I have created passing in the songid associated with the button that has been pressed
this.$store.dispatch('toggleSongPlaying', {songid: songid})
Depending on whether the song is playing or not, I wish to display the appropriate icon.
My simplified vuex store for my issue consists of the following:
const state = {
songs: {}
};
const mutations = {
update_song_playing(state, payload) {
var songObj = state.songs[payload.songid]
var playingBool = !songObj.playing
Vue.set(songObj, 'playing', playingBool)
}
};
const actions = {
toggleSongPlaying({ commit }, payload) {
commit("update_song_playing", payload)
}
};
const getters = {
getSongs: state => state.songs
};
The setting functionality is working fine, the issue is with reactivity. When the toggle button is pressed, the icon change does not occur. Triggering a rerender does however result in the icon changing. Within my component, I am using mapGetters like so:
computed: {
...mapGetters({
songs: "getSongs"
})
}
Is there something I am missing in order to get reactivity to work correctly with this nested object?
Thanks for any suggestions!
EDIT - Template code for list and icons
<v-list dense>
<v-subheader>Songs List</v-subheader>
<v-list-item-group v-model="activeSong" color="primary">
<v-list-item
v-for="(song, songID) in songs"
:key="songID"
>
<v-icon class="mr-3" @click.stop="toggleSongPlaying(songID)">{{song.playing ? 'mdi-pause' : 'mdi-play'}}</v-icon>
// song details etc...
<v-list-item-content>
<v-list-item-title>
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</v-list>
methods: {
toggleSongPlaying(songid) {
this.$store.dispatch('toggleSongPlaying', {songid: songid})
}
},
EDIT2 In a separate component in created, I populate the songs object with a song like so
created() {
var songid = "12"
var song = {
length: ...,
playing: false,
}
var payload = {
song: song,
songid: songid
}
this.$store.dispatch('addSong', payload)
},
Within Vuex
Action:
addSong({ commit }, payload) {
commit("add_song", payload);
}
Mutator:
add_song(state, payload) {
state.songs[payload.songid] = payload.song
},