VUEX - Many mapActions with same action name on the same page - vue.js

I have several differents files for a lot of modules.
Some of the share the same action name
There is some page that use 2 or more mapActions for different modules
On my page is something like this:
methods: {
...mapActions({
documents: ['setDocumentImage'],
documentAddress: ['setDocumentImage'],
selfie: ['setDocumentImage']
}),
}
All my modules have a action setDocumentImage
But the problem is that i have to invoke them like: this.setDocumentImage(file)
Is there a way to create an alias for each one of these mapAction that my page can differentiate?
Or how can I fix it?

Yes there is a way ! Here you are :
methods: {
...mapActions('documents', { setDocumentImage: 'setDocumentImage' }),
...mapActions('documentAddress', { setDocumentAddressImage: 'setDocumentImage' }),
...mapActions('selfie', { setSelfieDocumentImage: 'setDocumentImage' }),
}

You can use namespacing if you are using modules in composing your store.
Something like this:
const moduleA = {
namespaced: true, //namespacing set to true.
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
namespacedModuleA: moduleA,
b: moduleB
}
})
Then in your mapAction you can do this :
methods: {
...mapActions({
actionOfA: ['nameSpacedModuleA/actionOfA'],
actionOfB: ['actionOfB'],
}),
}
If you do not want to use mapActions, you can also do
this.$store.dispatch('nameSpacedModuleA/actionOfA')
More on namespacing with modules here

Related

I want to change count value by using v-model in vue app in vuex store

This code does not generate error but when I change my count it does not show the result on screen. Kindly help me in resolving the issue.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
lists: [
{
title: "User",
count: 15,
},
{
title: "Admin",
count: 41,
},
{
title: "Total Members",
count: 100,
},
{
title: "Manager",
count: 35,
}
]
},
mutations: {
updateMessage (state, count) {
state.lists.count = count
}
},
actions: {
},
modules: {
}
})
First thing, you don't need v-model to update your store. You can create a local copy and update it on the fly.
Second thing, I think you don't want to update not the whole counts of every objects but I guess you want to update an item in particular.
That's what I would do:
// 1. In component you watch state.lists and copy it immediately on init, deeply & on change:
data() {
return {
localCopyOfLists: []
}
},
watch: {
state.lists: {
immediate: true,
deep: true,
handler(v) {
this.localCopyOfLists = this.state.lists.map(x => (x))
}
}
}
// 2. Methods to change count of element in local list.
methods: {
updateItemInArray(index, count) {
this.localCopyOfLists[index].count = count
this.store.dispatch('SAVE_NEW_ARRAY', this.localCopyOfLists)
}
}
// 3. You update your store.
import Vue from 'vue'
export default new Vuex.Store({
actions: {
SAVE_NEW_ARRAY ({commit}, payload) {
commit('UPDATE_ARRAY', payload)
}
},
mutations: {
UPDATE_ARRAY (state, payload) {
Vue.set(state, lists, payload)
}
}
})

How to use this data from Vuex inside the component?

What is the best way to use this data from the Vuex store's Action in the needed component?
import axios from 'axios'
export default {
namespaced: true,
state: {
items: []
},
actions: {
fetchCategories ({state, commit}) {
return axios.get('/api/v1/categories')
.then(res => {
const categories = res.data
commit('setItems', {resource: 'categories', items: categories}, {root: true})
return state.items
})
}
}
}
Component
export default {
components: {
ThreadCreateModal,
ThreadList
},
data () {
return {
...
}
},
computed: {
...
},
created () {
...
},
methods: {
...
}
</script>
Where and how should I use that action for binding the data in this component?
Use mapState by import it from vuex and call it in computed:
computed: {
...mapState(['items']), // if you dont use namespace
...mapState("your_module_name", ['items'] ) // if you use namespace
},
then you can access it by this.items.
However, you can access it directly this.$store.state.items

Action is not defined as a method in the component vue.js

I'm trying to access an action as a method in component, But got error of
this.delete_notifaction is not a function
notifaction.js
export const actions = {
add_notifaction({ commit }, notifaction) {
commit("ADD_NOTIFACTION", notifaction);
},
delete_notifaction({ commit }, notificationToRemove) {
commit('DELETE_NOTIFACTION', notificationToRemove)
}
};
store/index.js
modules : {
notifaction
},
Component.vue
methods: mapActions('notifaction',["delete_notifaction"]),
mounted() {
this.delete_notifaction(this.notification);
}
Any Help?
Try this
methods: {
...mapActions(['delete_notifaction']),
}
See here for spread syntax
https://stackoverflow.com/a/48137766/10118668

how to get nested getters in vuex nuxt

i have store/index.js like this
new Vuex.Store({
modules: {
nav: {
namespaced: true,
modules: {
message: {
namespaced: true,
state: {
count: 0,
conversations: [],
},
getters: {
getCount: state => {
return state.count;
},
},
mutations: {
updateCount(state) {
state.count++;
},
},
actions: {},
},
requests: {
namespaced: true,
state: {
friends: [],
},
getters: {
getFriends: state => {
return state.friends;
},
},
mutations: {
pushFriends(state, data) {
state.friends.push(data);
},
},
actions: {
pushFriends(commit, data) {
commit('pushFriends', data);
},
},
},
},
},
},
});
i want to use getters in computed property i have tested like this
computed: {
...mapGetters({
count: 'nav/message/getCount',
}),
},
butt getting error
[vuex] unknown getter: nav/message/getCount
what is am missing here
i also want to make separate folder for every modules like my nav have 3 modules message, requests & notifications
i did try but nuxt blow up my codes
I think your index is wrong, the correct thing is to separate the modules independently, something like this:
in your store/index.js
export const state = () => ({
config: {
apiURL: 'https://meuapp.com'
}
})
export const mutations = { }
export const actions = { }
// getters
export const getters = {
test: state => payload => {
if (!payload)
return {
message: 'this is an messagem from index without payload test.', // you don't need pass any payload is only to show you how to do.
result: state.config
}
else
// return value
return {
message: 'this is an message from index test with payload.',
result: state.config, // here is your index state config value
payload: payload // here is yours params that you need to manipulate inside getter
}
}
}
here is your store/navi.js
export const state = () => ({
navi: {
options: ['aaa', 'bbb', 'ccc']
}
})
export const mutations = { }
export const actions = { }
// getters
export const getters = {
test: state => payload => {
if (!payload)
return {
message: 'this is a messagem from nav store without payload test.', // you don't need pass any payload is only to show you how to do.
result: state.navi
}
else
// return value
return {
message: 'this is an messagem from navi test with payload.',
result: state.navi, // here is your index state config value
payload: payload // here is yours params that you need to manipulate inside getter
}
}
}
then in your component you can use as a computed properties:
<template>
<div>
without a paylod from index<br>
<pre v-text="indexTest()" />
with a paylod from index<br>
<pre v-text="indexTest( {name: 'name', other: 'other'})" />
without a paylod from navi<br>
<pre v-text="naviTest()" />
with a paylod from navi<br>
<pre v-text="naviTest( {name: 'name', other: 'other'})" />
access getters from methods<br>
<pre>{{ accessGetters('index') }}</pre>
<pre v-text="accessGetters('navi')" />
<br><br>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
computed: {
...mapGetters({
indexTest: 'test',
naviTest: 'navi/test'
})
},
methods: {
accessGetters (test) {
if (test && test === 'index' ) {
console.log('test is', test) // eslint-disable-line no-console
return this.indexTest()
}
else if (test && test === 'navi') {
console.log('test is:', test) // eslint-disable-line no-console
return this.naviTest()
}
else {
return 'test is false'
}
}
}
}
</script>
Whenever possible separate your code into smaller parts, one part for each thing. This makes it easier for you to update and keep everything in order.
Hope this helps.
I came here to find a way to access the getters of a module that was nested inside another module in Vue.js and the following solution worked for me:
this.$store.getters['outerModuleName/innerModuleName/nameOfTheGetter']
Maybe this helps someone with a similar problem.

Is it possible to mutate a state prop in a module using another’s module mutator in vuejs2?

Lets say we have something like this:
const moduleA = {
state: { name: 'Cristian' },
namespaced: true,
}
const moduleB = {
state: { color: 'red' },
namespaced: true,
}
const store = new Vuex.Store({
state: { user: null, },
modules: {
a: moduleA,
b: moduleB
},
mutations: {
setPropValue(state, payload) {
for (let [key, value] of Object.entries(payload)) {
state[key] = value;
}
},
},
})
On my vue instance I have a firebase observer to get when the user logs in/out and change state accordingly. So what I want to achieve is something like this:
const payload = {
module: 'root',
payload: { user, },
}
this.$store.commit('setPropValue', {payload});
then for another module:
const payload = {
module: 'a',
payload: { name: 'Alexander', },
}
and run the same logic, but with different load and change the props from module a:
this.$store.commit('setPropValue', {payload});
Instead of committing to the mutation directly, consider using an action
this.$store.dispatch('setPropValue', { user });
Then in vuex, your action
actions: {
setPropValue({ commit }, { user }) {
commit("a/setName", user.name);
commit("b/setColor", user.favoriteColor);
}
}
Each module will need its own 'local' mutation in order to modify that modules state.
See https://vuex.vuejs.org/en/modules.html for details