vuex icon indicating copy to clipboard operation
vuex copied to clipboard

Access module namespace from within module

Open Vic-Dev opened this issue 6 years ago • 5 comments

What problem does this feature solve?

I want to be able to return different data from my module's getter if the name of the module matches the route name. Ie, I have many modules that all use the same underlying store, but are stored under different namespaces. Each module has a getter that attempts to compare it's namespace with the current route name, and then returns different data if the namespace matches the route name.

What does the proposed API look like?

There's a number of ways of making this information available within a store module. You could have it be another parameter that gets passed in to each function. Eg,

getters: {
  thing: (state, getters, rootState, rootGetters, namespace) {
    console.log(namespace);
  }
}

Or you could make it a property on the state I guess:

getters: {
  thing: (state, getters, rootState, rootGetters) {
    console.log(state._namespace);
  }
}

Vic-Dev avatar Apr 20 '18 13:04 Vic-Dev

I always use custom property state.name but it would be handy to have the access to the module's name from inside the module.

lattam avatar Jun 26 '18 13:06 lattam

@Vic-Dev, @lattam I found a solution for getting the module namespace. This requires references to the Store and state of the current module. Returning the result in an array so that it can be passed to the registerModule.

function getModuleNamespace(store, state) {
	const moduleNamespace = Object.keys(store._modulesNamespaceMap)
		.find(path => store._modulesNamespaceMap[path].context.state === state);
	if (typeof mouleNamespace === 'string') {
		return  moduleNamespace.slice(0, -1).split('/');
	}
}

This method can be used, for example, as follows:

// ...
actions: {
	actionRegisteringModule({ state }, payload) {
		this.registerModule([...getModuleNamespace(this, state), 'someModule'], someModule);
	}
}
// ...

You can modify the method so that it immediately adds a new module name to the end of the array.

sidelong44 avatar Jan 21 '19 23:01 sidelong44

The approach I took was inspired by @lattam 's comment

I created an action and mutation in the root module that accepts the store as an arg.

export const store = new Store({
    modules: {
        module1,
        module2,
    },
    actions: {
        bindNamespaces({commit}, {_modulesNamespaceMap}) {
            Object.entries(_modulesNamespaceMap).forEach(([namespace, module]) => {
                commit('bindNamespace', {module, namespace});
            });
        },
    },
    mutations: {
        bindNamespace(_, {module, namespace}) {
             Vue.set(module.state, '_namespace', namespace);
        },
    },
});

which then lets me bind namespaces to modules when the app is created.

const app = new Vue({
    el: '#app',
    store: require('./store').store,
    created() {
        this.$store.dispatch('bindNamespaces', this.$store);
    },
});

Probably not the best approach, but it's a decent work-around.

edreesjalili avatar Oct 30 '19 15:10 edreesjalili

The community really needs this, every comment here is a workaround, what is the reason for not having it yet? are there any side effects here?

#WeNeedIt

:smile:

Regards Vuex team!

jesusgn90 avatar Jan 03 '20 12:01 jesusgn90

Is there yet any solution to dynamically get module/namespace name from context?

CMQNordic avatar Apr 01 '22 23:04 CMQNordic