Changing getter value using state value in Vuex - vue.js

I have this getter that get the value of one item in the state:
boxdata: state => {
return state.boxchart.data
},
Now I have another item in state that I use to change the value of getter
Currently I do this when component is mounted but it seems that the data sometimes loads but sometimes does not:
computed: {
...mapGetters(["boxdata"]),
...mapState(['reference_fc'])
},
mounted() {
this.boxdata[0].chartOptions.series[0].data[0]=this.reference_fc.NSR.values
}
So I wonder how can I ensure that the boxdata getter is already updated on the first time that the component loads?

Vue cannot detect array element assignments. This is explained in Caveats.
Try this instead:
this.$set(this.boxdata[0].chartOptions.series[0].data, 0, this.reference_fc.NSR.values)

You shouldn't mutate data using getters. You should use mutations.
Getters are only to get derived state based on store state. see here
In your store :
mutations: {
setBoxdata(state, value) {
state.boxchart.data[0].chartOptions.series[0].data[0] = value;
}
}
In your component :
computed: {
...mapMutations("setBoxdata")
},
mounted() {
this.setBoxData(this.reference_fc.NSR.values);
}

Related

Computed properties and Vuex

I'm a little confused on how computed properties work with Vuex. I'm using a computed getter:
var selectDisplayValues = computed({
get() {
return store.getters['expense/getSelectDisplayValues'];
}
});
When the store data changes the computed prop also changes. So far so clear.
When now assigning a new value to the computed property - the value inside the store also changes. Not just the local value of the property. Why is that so? Won't I need a setter inside the computed prop to do so?
EDIT:
I'm assigning the new values like this.
selectDisplayValues.value[`inputData[${props.index}][${props.attribute}]`] = {placeholder_value: "Bitte wählen...", value: "", reassigned: false};
Also I'm using a v-model on a select dropdown for changing them according to the options value.
A new value wasn't assigned but existing value was mutated.
Getter-only computed ref has read-only value property that contains unmodified value.
If the intention is to make ref value deeply read-only, this needs to be explicitly done:
const selectDisplayValues = readonly(toRef(store.getters, 'expense/getSelectDisplayValues'))
I would personaly recommand using mapGetters from vuex : the mapgetters helper
I works like this :
You decalre a getter un your vuex store :
const store = createStore({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos (state) {
return state.todos.filter(todo => todo.done)
}
}
})
And in your vue component :
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
...mapGetters({
doneCount: 'doneTodosCount'
})
}
}
You can then access value from your getter with this.doneCount
If the store change the computed value wil automatically change

Vuex State watch over Compute not working

I have empty state in the beginning like so
new Vuex.Store({
state: {
comboBoxNewValues: {}
},
Over time, there are mutations which changes the state like so
this.$store.commit('addComboBoxValues', { input: 'foo', value: ['value': 1, 'name': 'bar']});
Using the following mutation code
mutations: {
addComboBoxValues(state, _value) {
state.comboBoxNewValues[_value.input] = _value['value'];
},
}
It works perfectly and mutations also changes the state, Now I want to perform some action on change of the state so in my component I added a computed property like so
computed: {
getComboBoxNewValues() {
return this.$store.state.comboBoxNewValues;
}
}
When I debug using vue-dev-tools, the components computed property has data. Whenever the data changes using mutation in the vuex, that data is reflected in the computed property as well.
Now I add a watcher to it like so
watch: {
getComboBoxNewValues:{
handler: function(to, from) {
console.log("reload");
},
deep: true
}
}
The problem is that the never never gets called, no matter how many times the data has changed in the computed property. Please advice on what I am missing.

How to watch for vuex state?

I need do fire a function within component when my vuex state data change, but it does not work , is there any wrong usage about watch hook for vuex?
const state = {
currentQueryParameter:[],
};
const mutations = {
currentQueryParameter(state,info){
state.currentQueryParameter[info.index]=info.value
Vue.set(info, info.index, info.value);
}
}
in component
watch: {
'$store.state.currentQueryParameter': function() {
console.log("changed")
this.getData()
}
},
What you are doing is technically correct and will work.
However several thing are still going wrong:
If you want your state to be reactive you need to fill Arrays with native array methods (.push(), .splice() etc). Vue.set() is only used to set Object properties.
You are watching currentQueryParameter, which is an Array. Its value does not change through your mutation - it stays the same Array. If you want to watch nested elements as well, you need to use the deep flag in your watcher, like so:
watch: {
'$store.state.currentQueryParameter': {
deep: true,
handler(newVal) {
console.log('queryParameter changed');
}
}
}
I don't know what you are trying to do with this one in your mutation:
Vue.set(info, info.index, info.value); but you should not mutate the properties you pass to a function.

Computed property react to localstorage change

I'm saving an array into local storage
and adding/removing from the array like.
I want the count of the array to update in the component as and when new items get added to the array in localstorage
I am using a computed property:
numOfCodes: {
// getter
get: function() {
let storageItems = localStorage.getItem("items");
if (storageItems) {
var items = JSON.parse(storageItems);
return items.length;
}
return 0;
}
}
The count is not changing as expected. it remains the same.
I have tried using vuex, but still have the issue. the goal is having the value react to the localstorage change
I think a solution to this would be to use vuex, I've mocked up an example below:
On your component:
computed: {
...mapGetters({
itemsCount: 'mockLocalStorage/itemsCount'
})
},
created() {
this.setItems(...);
},
methods: {
...mapActions({
setItems: 'mockLocalStorage/setItems'
})
}
In vuex:
state = {
items: []
};
getters = {
itemsCount: state => state.items.length
};
actions: {
setItems({ commit }, items) {
localStorage.setItem('items', items);
commit('setItems', items);
}
};
this.itemsCount would then be reactive in your component, and you could create a few more actions to add and remove individual items.
The localStorage does not share the reactivity system of Vue. This whole process is handled by Vue itself. See also here. I think you should be able to manually trigger a re-render by forcing Vue to update all of its components using forceUpdate. However, keep in mind that you would have to trigger the re-render whenever you update the localStorage or whenever you expect it to be updated.
Use a watcher.
props: ['storageItems', 'itemsLength'],
watch: {
storageItems: function(newVal, oldVal) {
this.storageItems = newVal
this.itemsLength = newVal.length
}
}

Vue: Why is this computed property not reactive?

Here is a computed getter and setter from a vue component:
paidStartHours : {
get() {
return moment(this.position.paid_start, global.DB_DATETIME).format('HH');
},
set(value) {
this.$store.commit({
type : 'updatePaidStartHours',
newValue : value,
position : this.position
});
}
}
On get, it returns the hours (HH) from position.paid_start. On set, it commits a store mutation, which essentially recreates the time string for position.paid_start.
In is bound (two-way) to an input as follows:
<input v-model="paidStartHours" type="text">
On initial load, computed property paidStartHours is correct (per Vue Tools).
When I update the input however, the value of paidStartHours does not change. I know that the commit is successful, because the props that are handed to the component are correct. It makes no sense to me.
EDIT:
The code in the updatePaidStartHours mutation has changed a number of times. For example, I tried this:
updatePaidStartHours(state, payload) {
payload.position.paid_start = 999;
}
The value of the passed prop changed to 999, however the value of the computed prop remained the same.
EDIT II:
I don't think it is worth trying to resolve this issue because I think my whole Vue / Webpack / Node installation is very sick. For example, this morning I delightedly followed this answer, Vuejs and Webpack: Why is store undefined in child components, to import an instantiated store into my App. It all seemed fine but after about 8 hours of stuffing about I see that NO store properties are reactive. I reverted to importing the config only, and now most of my store properties are reactive, but sadly not the ones above. I think I need to abandon the approach until I get time to revisit blow away my Vue / Webpack / Node install and start again.
Vuex mutations should be called from Vuex actions only - so in your code you should dispatch an action, not a mutation. Also, your mutation function is expected to mutate the store argument - not the payload one. Your getter is also wrong - it should use this.$store.getters and not your local component data.
paidStartHours : {
get() {
return moment(this.$store.getters.position.paid_start, global.DB_DATETIME).format('HH');
},
set(value) {
this.$store.dispatch('updatePaidStartHours',value);
}
}
Vuex module:
// initial state
const state = {
position:
{
paid_start: null
}
};
// getters
const getters = {
position: (state) => state.position
}
// actions
const actions = {
updatePaidStartHours ({commit}, payload)
{
commit('SET_START_HOURS', payload);
}
}
// mutations
const mutations = {
SET_START_HOURS (state, payload)
{
state.position.paid_start = payload;
}
}