Dynamic store value in Vuex - vue.js

I have a simple store, and I want to have a store value that sums up all the values in an array automatically, but I am unsure what is the best approach with mutations, methods or computed values.
export default {
namespaced: true,
state: {
my_list_values: [10,9,10],
list_sum: 29
}
}
I would like for the list_sum value to function that sums up my_list_values.

You can make use of getter which holds your logic for listSum and can be used in components
export default {
namespaced: true,
state: {
my_list_values: [10,9,10],
}
getters: {
listSum (state) {
//logic to sum values
}
}
}
You can use this getter anywhere in your components as below
import { mapGetters } from 'vuex'
computed: {
...mapGetters([
'listSum',
// ...
])
}
OR
this.$store.getters.listSum
For Ref : Getters

Related

In Vuex, how do I access the root state from the state definition within a namespaced module?

I'm using Vuex 3.2.0 with modules.
In one of my modules I need access to the rootState from within the initial state: { ... } definition. How do I do this?
// my-module.js
export default {
namespaced: true,
state: {
// I can't actually use `rootState` here so how do I access it?
foo: rootState.appConfig.bar + 'baz';
},
mutations: { ... },
actions: { ... },
getters: { ... }
}
I don't want to use a getter without any actual state value because I need to be able to mutate this value.

Computed property was assigned to but it has no setter

What is the correct syntax/hooks to make this work for myVal?
My code looks like this:
<v-item-group v-model="myVal" ...
import { mapActions, mapGetters } from 'vuex';
export default {
computed : {
...mapActions({
myVal: 'myModulePath/setMyVal'
}),
...mapGetters({
myVal: 'myModulePath/getMyVal'
}),
},
}
The store looks like:
actions: {
setMyVal({commit}, value){commit('someMutation',value);}
getters: {
getMyVal: state => { return state.myVal;}
I'm not sure how to wire it so the 'setter' works and the error message goes away.
I've also tried this to no avail:
...mapState('myModulePath', ['myVal'])
You need to define a single computed with a get and a set function. Maybe:
export default {
computed : {
myVal: {
get() { return this.$store.getters.getMyVal; },
set(newValue) { this.$store.dispatch('setMyVal', newValue); }
}
},
}
You need to tell the vue component what to do when the computed property is assigned a new value
computed: {
myVal: {
get: () => this.$state.store.getters.myModulePath.getMyVal,
set: (value) => this.$state.commit('someMutation', value )
}
}
Note that I use the setter instead of the action. Using an action in the computed property setter is a bad idea because actions are usually asynchronous and can cause headaches trying to debug the computed property later.

vuejs 2 how to watch store values from vuex when params are used

How can I watch for store values changes when params are used? I normally would do that via a getter, but my getter accepts a param which makes it tricky as I've failed to find documentation on this scenario or a stack Q/A.
(code is minimized for demo reasons)
My store.js :
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
let report = {
results: [],
};
export const store = new Vuex.Store({
state: {
broken: Object.assign({}, report),
},
results: (state) => (scan) => {
return state[scan].results
},
});
vue-component.vue :
computed: {
...mapGetters([
'results',
]),
watch: {
results(){ // How to pass the param ??
// my callback
}
So basically I would like to find out how to pass the param so my watch would work.
In my opinion, there is no direct solution for your question.
At first, for watch function, it only accept two parameters, newValue and oldValue, so there is no way to pass your scan parameter.
Also, your results property in computed, just return a function, if you watch the function, it will never be triggered.
I suggest you just change the getters from nested function to simple function.
But if you really want to do in this way, you should create a bridge computed properties
computed: {
...mapGetters([
'results',
]),
scan() {
},
mutatedResults() {
return this.results(this.scan);
},
watch: {
mutatedResults() {
}
}
}

Value of vuex getter not updating when switching between routed components

I have a vuex getter that takes the value of an array from my state.
import Vue from 'vue'
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
tableRow: [
{
"name": 1,
"numSongs": 2,
"Year": 3
}
]
},
getters:{
tRow : state => {
return state.tableRow
}
}
});
I have a function that takes the values from a table row and sets the value of it to my computed property for the getter.
$("#table1 tr").click(function () {
var list = [];
var $row = $(this).closest("tr"),
$tds = $row.find("td");
list.push({ name: $tds.eq(0).text(), numSongs: $tds.eq(1).text(), Year: $tds.eq(2).text() });
// self.$store.state.tableRow = list;
this.tabRow = list;
console.log(this.tabRow);
self.passData();
});
});
},
computed: {
tabRow(){
return this.$store.getters.tRow;
}
},
Then in another one of my routed components i set the same computed property and then try to call it in the template but the value it outputs is the default values i gave it.
mounted: function () {
var self = this;
console.log(this.tabRow)
// self.passedRow = self.$store.state.tableRow;
self.passedRow = this.tabRow;
this.startDoughnut(this.$refs.canvas, 'Doughnut');
},
computed: {
tabRow(){
return this.$store.getters.tRow;
}
I am not properly efficient with vuex yet so i am not sure why this won't work any help would be appreciated.
What you are trying to do here is not possible in vue compute property and also in Vuex. Computed properties and vuex getters areread only.
this.tabRow = list;
======================
computed: {
tabRow(){
return this.$store.getters.tRow;
}
Do this
computed: {
tabRow(){
get: function () {
return this.$store.getters.tRow;
},
set: function (newValue) {
commit('SET_TABLEROW', newValue)
});
}
}
In store add a mutation
mutations:{
SET_TABLEROW: (state,list) => {
state.tableRow=list
}
}
refer https://vuex.vuejs.org/en/mutations.html
I have a function that takes the values from a table row and sets the value of it to my computed property for the getter.
Examining your second block of code:
You are trying to set the value of list to the computed property tabRow. Computed properties are by default getter-only, i.e we can only get or acess a value not set a value.
As far as I understood your problem you want to take the value from the table row and add it to the tableRow property in your vuex state. For that you need a mutation
$("#table1 tr").click(function () {
var $row = $(this).closest("tr"),
$tds = $row.find("td");
var list = { name: $tds.eq(0).text(), numSongs: $tds.eq(1).text(), Year: $tds.eq(2).text() };
self.$store.commit('addTableRow', list);
self.passData();
});
In you vuex store add the mutation
import Vue from 'vue'
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
tableRow: [
{
"name": 1,
"numSongs": 2,
"Year": 3
}
]
},
getters:{
tRow : state => {
return state.tableRow
}
},
mutations: {
addTableRow: (state, list) => {
state.tableRow.push(list);
}
}
});

Pass params to mapGetters

I use vuex and mapGetters helper in my component. I got this function:
getProductGroup(productIndex) {
return this.$store.getters['products/findProductGroup'](productIndex)
}
Is it possible to move this somehow to mapGetters? The problem is that I also pass an argument to the function, so I couldn't find a way to put this in mapGetters
If your getter takes in a parameter like this:
getters: {
foo(state) {
return (bar) => {
return bar;
}
}
}
Then you can map the getter directly:
computed: {
...mapGetters(['foo'])
}
And just pass in the parameter to this.foo:
mounted() {
console.log(this.foo('hello')); // logs "hello"
}
Sorry, I'm with #Golinmarq on this one.
For anyone looking for a solution to this where you don't need to execute your computed properties in your template you wont get it out of the box.
https://github.com/vuejs/vuex/blob/dev/src/helpers.js#L64
Here's a little snippet I've used to curry the mappedGetters with additional arguments. This presumes your getter returns a function that takes your additional arguments but you could quite easily retrofit it so the getter takes both the state and the additional arguments.
import Vue from "vue";
import Vuex, { mapGetters } from "vuex";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
myModule: {
state: {
items: [],
},
actions: {
getItem: state => index => state.items[index]
}
},
}
});
const curryMapGetters = args => (namespace, getters) =>
Object.entries(mapGetters(namespace, getters)).reduce(
(acc, [getter, fn]) => ({
...acc,
[getter]: state =>
fn.call(state)(...(Array.isArray(args) ? args : [args]))
}),
{}
);
export default {
store,
name: 'example',
computed: {
...curryMapGetters(0)('myModule', ["getItem"])
}
};
Gist is here https://gist.github.com/stwilz/8bcba580cc5b927d7993cddb5dfb4cb1