Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js 'v-bind:class' doesn't update even though model does

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?

like image 478
Stephan Avatar asked Dec 16 '16 13:12

Stephan


People also ask

Does Vue automatically update?

message: 'Hello Vue. js! ' When clicking on the #app element Vue does indeed automatically update the view!

What does V-bind do in Vue?

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.

Does Vue use two-way binding?

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.


1 Answers

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

like image 88
Stephan Avatar answered Oct 21 '22 15:10

Stephan