panthro
panthro

Reputation: 24061

Changing a vuex state from a different component?

I have a component (modal) which relies on a store. The store has the state of the modal component - whether it is active or not.

I need to be able to call this modal to open from other components or even just on a standard link. It opens by adding an .active class.

How can I change the state of the store - either by calling the stores action or calling the modal components method (which is mapped to the store).

Modal Store:

class ModalModule {
    constructor() {
        return {
            namespaced: true,

            state: {
                active: false,
            },

            mutations: {
                toggleActive: (state) => {
                    return state.active = ! state.active;
                },
            },

            actions: {
                toggleActive({ commit }) {
                    commit('toggleActive');
                },
            },

            getters: {
                active: state => {
                    return state.active;
                }
            }
        };
    }
}

export default ModalModule;

Vue Component:

<template>
    <div class="modal" v-bind:class="{ active: active }">
        <div class="modal-inner">
            <h1>modal content here</h1>
        </div>
        <div class="modal-close" v-on:click="this.toggleActive">
            X
        </div>
    </div>
</template>

<script>

import { mapGetters, mapActions } from 'vuex';

export default {
    computed: {
        ...mapGetters('Modal', [
            'active',
        ])
    },
    methods: {
        ...mapActions('Modal', [
            'toggleActive',
        ]),
    }
}
</script>

And somewhere else I want to be able to have something like:

<button v-on:click="how to change the state??">OPEN MODAL</button>

Edit:

Here's the store:

import Vuex from 'vuex';
import ModalModule from './ModalModule'; 
class Store extends Vuex.Store {
    constructor() {

        Vue.use(Vuex);

        super({
            modules: {
                Modal: new ModalModule(),
            }
        });

    };
}

Upvotes: 3

Views: 9429

Answers (2)

Vamsi Krishna
Vamsi Krishna

Reputation: 31352

You do not need an action for your particular usecase . You just just define a mutation as you are just changing the boolean value of a property in a state. Actions are for async functionality. You usecase is just synchronous change of Boolean value

So you can do

<button v-on:click="$store.commit('toggleActive')">OPEN MODAL</button>

EDIT: Just export a plain object

const ModalModule = {
            namespaced: true,

            state: {
                active: false,
            },

            mutations: {
                toggleActive: (state) => {
                    return state.active = ! state.active;
                },
            },

            actions: {
                toggleActive({ commit }) {
                    commit('toggleActive');
                },
            },

            getters: {
                active: state => {
                    return state.active;
                }
            }
}

export default ModalModule;// export the module

Even remove the class based definition of the store

import Vue from 'vue'
import Vuex from 'vuex';
import ModalModule from './ModalModule'; 

Vue.use(Vuex);

export const store = new Vuex.Store({
    modules: {
        ModalModule
    }
});

And change it like this in you component for mapping of the mutation (<MODULE_NAME>/<MUTATION_NAME>)

...mapMutations([
    'ModalModule/toggleActive' 
]) 

Upvotes: 5

jun
jun

Reputation: 56

You can access the store from your components via this.$store. There you can call your actions and mutations. So

<button v-on:click="$store.commit('your mutation name', true)">OPEN MODAL</button>

Upvotes: 3

Related Questions