Reputation: 405
I search for a clean way to use v-model and vuex store.
Vuex provide several helpers methods are pretty usefull but a little bit annoying when using with v-model.
The way I do today to use v-model and my modularized store is like
computed: {
type: {
get() {
return this.$store.state.mymodule.type;
},
set(newValue) {
this.$store.dispatch('mymodule/setType', newValue)
}
}
This works BUT I found better to take profit of vuex helpers to avoid boilerplate code (this.$store, module name, ...)
Ok, so I firstly want to get rid of module name. Vuex provide a great createNamespacedHelpers which return modularized helpers.
Let's use it :
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
So, ok, we now have a clean mapState and mapActions functions which are module dedicated.
computed: {
...mapState(['type']) // No need here to specify module name :)
}
Pretty cool but since mapState has only get function, I can't set a dispatch function to update data...
In case of using v-model, I find helpers unusable. I can't use mapState, thus I can't use createNamespacedHelpers.
So : How can I use the benefit of Vuex helpers functions and v-model to work together ?
Upvotes: 4
Views: 3295
Reputation: 827
Try this.
// in some utils/vuex.js file
export const mapSetter = (state, setters = {}) => (
Object.keys(state).reduce((acc, stateName) => {
acc[stateName] = {
get: state[stateName],
};
// check if setter exists
if (setters[stateName]) {
acc[stateName].set = setters[stateName];
}
return acc;
}, {})
);
In your component.vue file
import { mapSetter } from 'path/to/utils/vuex.js';
...
export default {
name: 'ComponentName',
computed: {
...mapSetter(
mapState({
result: ({ ITEMS }) => ITEMS.result,
total: ({ ITEMS }) => ITEMS.total,
current: ({ ITEMS }) => ITEMS.page,
limit: ({ ITEMS }) => ITEMS.limit,
}),
{
limit(payload) {
this.$store.dispatch({ type: TYPES.SET_LIMIT, payload });
},
},
)
},
}
now v-model binding should work.
Upvotes: 0
Reputation: 405
The way I finally found the most readable is the following :
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
Used like this :
computed: {
...mapGetters(['type'])
},
methods: {
...mapActions(['setType'])
}
And without the v-model
<input :value="type" @input="setType($event.target.value)">
Upvotes: 1
Reputation: 2489
You can't. There is no elegant way to combine helpers with v-model. But v-model is just a syntactic sugar, so maybe the most readable way is to use the helpers
computed: {
...mapGetters('path/to/module', ['type'])
},
methods: {
...mapActions('path/to/module', ['setType'])
}
without the v-model
<input :value="type" @input="setType">
Upvotes: 2