I've got a list of items, and i want to apply a style to the currently selected one. I'm also using Vuex to manage the state.
My list component:
const List = Vue.component('list', {
template:
'<template v-if="items.length > 0">' +
'<ul class="list-group md-col-12">' +
'<a href="#" v-for="(item, index) in items" class="list-group-item list-group-item-action" v-bind:class="{ active: item.isActive }" v-on:click="selectItem(index);">{{ g.text }}</a>' +
'</ul>' +
'</template>'
computed: {
items: function() {
return this.$store.state.items;
}
},
methods: {
selectItem: function (index) {
this.$store.commit('selectItem', index);
}
}
});
My store:
const store = new Vuex.Store({
state: {
items: [],
currentIndex: -1
},
mutations: {
selectItem: function(state, index) {
if (index === state.currentIndex) {
return;
}
if (state.currentIndex > -1) {
delete state.items[state.currentIndex].isActive;
}
state.currentIndex = index;
state.items[state.currentIndex].isActive = true;
}
}
});
What I see, also using the Vue 'tab' in Chrome DevTools is that whenever I click on an item of the list, the "items" array is being correctly updated, but the class is not set on them.
Also, using the time-travel debugging to go through all the mutations, in that case the class is set.
Any idea why this behavior and how to fix it?
message: 'Hello Vue. js! ' When clicking on the #app element Vue does indeed automatically update the view!
The v-bind directive instructs Vue to keep the element's id attribute in sync with the component's dynamicId property. If the bound value is null or undefined , then the attribute will be removed from the rendered element.
Two-way binding is a powerful feature that, if used properly, can significantly speed up your development process. It reduces the complexity of keeping user input consistent with the application data model. In Vue, two-way binding is accomplished using the v-model directive.
It turns out I should have read the docs more in depth. In particular Change Detection Caveats.
The solution was to change the store mutation thus:
selectItem: function(state, index) {
if (index === state.currentIndex) {
return;
}
if (state.currentIndex > -1) {
Vue.delete(state.items[state.currentIndex], 'isActive');
}
state.currentIndex = index;
Vue.set(state.items[state.currentIndex], 'isActive', true);
}
Key here is to use the Vue.delete
and Vue.set
functions.
Other answer that helped me https://stackoverflow.com/a/40961247/525843
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With