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
Related
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.
I am trying to pass data to a v-select dropdown.
This of course works:
computed: {
itemDropdown() {
const menuItems = {
id: "1",
name: "Joe"
}
return menuItems;
}
}
But when I try:
computed: {
itemDropdown() {
const newArray = [...this.data.originalItems];
newArray.map(item => {
item.name = "myCoolNewName";
});
return newArray;
}
}
It mutates the original array.
I have also tried copying the object:
computed: {
itemDropdown() {
const newObj = { ...this.data };
newObj.items.map(item => {
item.name = "myCoolNewName";
});
return newObj;
}
}
Not sure what I’m missing, but wondering if there is a work around. Thanks for any help :slight_smile:
You are using the map array method wrong.
The first thing you need to know, is that the map method returns a new array, so you have to either return the result of your map function or save it in a variable, otherwise you will just be looping through your array without ever saving it anywhere.
Another thing is about how you use the map method.
Here I have made an example of how it should work with your code:
computed: {
itemDropdown() {
return this.data.originalItems.map(item => {
return {
name: "myCoolNewName"
}
});
}
}
The big difference you should notice, is that inside the map function, we have to return what we want each object to look like, after we have gone through it. We want it to give us the object back, but make some changes to it, so we have to actually return an object and change what we want in that.
What you were doing before, was refering to the item in the old array, and assigning it a new value, instead of returning a new object with your changes.
You can read about the array.map method here
Hope that makes sense :)
I have this object of arrays that I'm tryin to watch every update of.
myData = {
"299":[527],
"376":[630,629]
}
I read this documentation on watching an object which instructed to use either this.$set(object, propertyName, value) or Object.assign({}, this.object, dataToBeAppended) to watch an object. I used this.$set.
export default {
...
data() {
return {
myData: {},
};
},
watch: {
myData(newVal) {
console.log(`🔴localStorage`);
},
},
methods: {
onFoldChange(propertyName) {
const newArr = [...]
this.$set(this.myData, propertyName, newArr);
},
}
}
Unlike what I expected, vue captures changes on property only. Changes in value to an existing property are not being watched. For example, if a property "299" was newly added, it will print 🔴localStorage. When the value of a property "299" is updated from [527] to something else, nothing is fired. When I print myData, I see every value updated correctly. It is just that watch isn't capturing the changes.
The documentation also described we can watch an array using this.$set(this.myData, indexOfItem, newValue) so I also tried array version of the above code, like this.
this.$set(this.myData[propertyName], index, newValueToAdd);
This time it doesn't listen at all. Not even the first entry.
Is there any better way to solve this issue? How do others watch an object? Is the complication coming from the type of values (array) ?
Currently, myData watcher observes only an object. Object contains pointers to arrays as in JS Objects & Arrays are passed by reference not by copy. That's why it can detect only changes in keys and with simple values. If you want to observe it deeper - I mean also those subarrays (or subobjects) - just use deep watch.
watch: {
myData: {
deep: true,
handler (newVal) {
console.log(`🔴localStorage`);
}
}
}
Another possible solution could be to use some Array.prototype operation to modify an array if it already exists. E.g:
methods: {
onFoldChange(propertyName) {
if (propertyName in this.myData && Array.isArray(this.myData[propertyName])) {
this.myData[properyName].push(162) // Some random value
} else {
const newArr = [...]
this.$set(this.myData, propertyName, newArr);
}
},
}
i'm trying to watch an array declarated in data method (the 'validated' variable). I already have a watcher to an input (legal_name) and it works correctly but the array watcher doesnt give any response. Any idea?
export default {
data() {
return {
legal_name : '',
validated: [],
errors: []
}
},
watch: {
validated() {
console.log('modified')
},
legal_name(value) {
this.eventName();
this.legal_name = value;
this.checkLength(value, 3);
}
},
methods: {
checkLength(value, lengthRequired) {
if(value.length < lengthRequired) {
this.errors[name] = `Debes ingresar al menos ${lengthRequired} caracteres`;
this.validated[name] = false;
return false;
}
this.errors[name] = '';
this.validated[name] = true;
return true;
},
eventName() {
name = event.target.name;
}
}
}
You need to call Vue.set() for arrays, and NOT use indexing such as
foo[3]= 'bar'
Vue DOES recognize some operations, such as splice and push, however.
Read more about it here: https://vuejs.org/2016/02/06/common-gotchas/ and here: https://v2.vuejs.org/v2/guide/list.html#Array-Change-Detection
So for your code, and using the Vue handy helper method $set:
this.validated.$set(name, true);
Why...
Javascript does not offer a hook (overload) for the array index operator ([]), so Vue has no way of intercepting it. This is a limitation of Javascript, not Vue. Here's more on that: How would you overload the [] operator in javascript
data: {
addItemArray: [],
}
I have initialize one array inside data and then inside methods i am added some code:
var self = this;
{
self.cacheDom.$submitItem.click(function () {
self.addItemArray.push({
‘id’: $(’#accountSearch’).data(‘id’).trim(),
‘name’: $(’#accountSearch’).val().trim(),
‘type’: $(’#accountDropdown option:selected’ ).text().trim()
});
$(’.addItemMenu’).hide();
});
}
i pushing the data into addItemArray. Then another one click function inside methods that time i need the addItemArray items. But i getting always a empty array.
Thanks