How to locally store a computed variable property once in data - vue.js

I have a computed variable getting a value from the VUEX store. I only want to get this value once, and then save it locally into a variable so I can edit the said variable without doing any mutations on my store value. How can this be done?
Any help will be really appreciated.

What you can do is create a computed property with a get and set method:
data() {
return {
myValueCopy: null
}
},
computed: {
myValue: {
get() {
if (this.myValueCopy === null) {
return this.$store.getters.myValue;
}
return this.myValueCopy;
},
set(value) {
this.myValueCopy = value;
}
}
}
If there's no local copy of the data return the store value, else return the copy. When setting the data, update the local copy not the store.

I ended up using something similar to the other answer:
data() {
return {
LocalText: { type: String },
}
},
computed: {
...mapGetters('store', ['storevar']),
currentText: function () {
return this.storevar
},
},
created() {
this.LocalText= this.currentText
}
What I have done here is that I first made a new variable for the text to be locally stored - LocalText. I have also added a getter that gets the store variable from the store and a computed function that returns the value of the storevar. Finally, I have assigned the value of the storevar to my LocalText when the page is first created using the created() function.

Related

Update all object property of an array using vuex

I am trying to update a single property of an object from an array using vuex.
here is my code in store file.
export default{
namespaced: true,
state: {
customers: null,
},
mutations: {
UPDATE_MODIFIED_STATE(state, value) {
state.customers = [
...state.customers.filter(item => item.Id !== value.Id),
value,
];
},
},
And below code is from my .vue file.
export default {
computed: {
customerArray() {
return this.$store.state.CustomerStore.customers;
},
},
methods: {
...mapMutations('CustomerStore', ['UPDATE_MODIFIED_STATE']),
updateCustomers() {
if(someCondition) {
this.customerArray.forEach((element) => {
element.IsModified = true;
this.UPDATE_MODIFIED_STATE(element);
});
}
/// Some other code here
},
},
};
As you can see I want to update IsModified property of object.
It is working perfectly fine. it is updating the each customer object.
Just want to make sure, is it correct way to update array object or I should use Vue.set.
If yes, I should use Vue.set, then How can I use it here.
You are actually not mutating your array, what you do is replacing the original array with a new array generated by the filter function and the passed value. So in your example there is no need to use Vue.set.
You can find more information about replacing an array in the vue documentation.
The caveats begin however when you directly set an item with the index or when you modify the length of the array. When doing this the data will no longer be reactive, you can read more about this here.
For example, consider the following inside a mutation:
// If you update an array item like this it will no longer be reactive.
state.customers[0] = { Id: 0, IsModified: true }
// If you update an array item like this it will remain reactive.
Vue.set(state.customers, 0, { Id: 0, IsModified: true })

vuex store not refresh computed property

Following the tutorial at this web address http://stackabuse.com/single-page-apps-with-vue-js-and-flask-state-management-with-vuex/, I encountered a problem that the function in the computed property was not automatically invoked after the state in the store was changed. The relevant code is listed as following:
Survey.vue
computed: {
surveyComplete() {
if (this.survey.questions) {
const numQuestions = this.survey.questions.length
const numCompleted = this.survey.questions.filter(q =>q.choice).length
return numQuestions === numCompleted
}
return false
},
survey() {
return this.$store.state.currentSurvey
},
selectedChoice: {
get() {
const question = this.survey.questions[this.currentQuestion]
return question.choice
},
set(value) {
const question = this.survey.questions[this.currentQuestion]
this.$store.commit('setChoice', { questionId: question.id, choice: value })
}
}
}
When a radio button in the survey questions is chosen, selectedChoice will change the state in the store. However surveyComplete method was not called simultaneously. What's the problem? Thanks in advance!
surveyComplete() method does not 'spy' your store, it will be updated, when you change this.survey.questions only. So if you modify the store, nothing will happen inside surveyComplete. You may use the store inside the method.

Declaring variable in "data" section as an alias to $root is not reactive

I declare variable in main.js:
data: {
globalData: {}
}
I want to avoid using this.$root.globalData all the time — so I use local variable in a component as an alias to "global variable":
data() {
return {
localAlias: this.$root.globalData,
}
}
Then I fetch global variable from a server in main.js (simulate by setTimeout):
create() {
window.setTimeout(() => {
this.globalData = {a:1, b:2};
}, 1500);
}
And localAlias remains equal to initial value.
How to make it work? I don't need Vuex yet, I just grab data from server and use it read-only.
Example
Instead of using data you can use computed. It will solve your problem.
computed: {
localAlias: function() {
return this.$root.globalData;
}
}
I have updated the example
The reason localAlias doesn't change is because it still points to the same object, while you re-point this.$root.globalData to a new object. One way to do it is of course to use computed as the other answer suggested. Another way to solve it it to just change the properties instead of re-binding the entire object:
create() {
window.setTimeout(() => {
this.globalData.a = 1;
this.globalData.b = 2;
}, 1500);
}
This is less versatile though and will scale worse if the object becomes bigger.

How can read changing data in methods after created with Vue.js

My code like this:
<tempalte>
<div>{{contents}}</div>
</tempalte>
<script>
{
//...something
data: function() {
return { contents: null }
},
methods: {
test() {
console.log(this.contents)
}
},
created () {
// do something...
this.contents = someValue
this.test()
}
}
</script>
And when created excuted then call test methods, the print result is old value null.
But the {{contents}} is the new Value.
How can I get new value of data in methods after created assign new value and call the methods ?
I has already fixed it. If I call methods in updated (), it can work.
If you want to know the reasons, you can read this post:
https://v2.vuejs.org/v2/guide/reactivity.html

Two-way filter updating on the fly | Vue.js

How one can do custom two-way filter for model, updating on the fly in Vue.js.
The following code example from docs works on input blur. But I need it work on keypress.
Vue.filter('currencyDisplay', {
read: function(val) {
return '$'+val.toFixed(2)
},
write: function(val, oldVal) {
var number = +val.replace(/[^\d.]/g, '')
return isNaN(number) ? 0 : parseFloat(number.toFixed(2))
}
})
Many thanks in advance for any help!
You can apply a filter to a Vue data property by creating a computed property with a get and set method that fire the read and write methods of the filter, respectively:
data() {
return {
foo: 0,
}
},
computed: {
filteredFoo: {
get() {
return Vue.filter('currencyDisplay').read(this.foo);
},
set(value) {
this.foo = Vue.filter('currencyDisplay').write(value);
}
}
}
Here's a working fiddle.