Reputation: 1180
Below here i provide a sample code. So what happens here is, i have some objects that i will load from API. The object later will be extended by the UI, in case that some of property that will be used for binding in the UI missing #app2. Under normal condition, if all the properties are provided like in #app1, the Vue will do the binding recursively to the content of the data object. But currently, in #app2, the property is missing and in the UI logic, i add the missing property.
The problem now is, when i added the property that way, the app2.contentObject.toggleStatus
is not vue's object with getter and setter. how can i manually reinitialize the state of getter and setter so that the changes will be reflected in UI?
var app1 = new Vue({
el: "#app1",
data: {
contentObject: {
toggleStatus: false
}
},
computed: {
content: function(){
var contentObject = this.contentObject;
return contentObject;
}
},
methods: {
toggle : function(){
this.contentObject.toggleStatus = !this.contentObject.toggleStatus;
}
}
})
var app2 = new Vue({
el: "#app2",
data: {
contentObject: {
}
},
computed: {
content: function(){
var contentObject = this.contentObject;
contentObject.toggleStatus = false;
return contentObject;
}
},
methods: {
toggle : function(){
this.contentObject.toggleStatus = !this.contentObject.toggleStatus;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app1">
current toggle status: {{content.toggleStatus}}<br/>
<button @click="toggle">Toggle (working)</button>
</div>
<div id="app2">
current toggle status: {{content.toggleStatus}}<br/>
<button @click="toggle">Toggle (not working)</button>
</div>
Upvotes: 0
Views: 524
Reputation: 31352
1. In app2
vue instance's case you are trying to add a new property toggleStatus
and expecting it to be reactive. Vue cannot detect this changes. So you got to initialize the properties upfront as you did in app1
instance or use this.$set()
method. See Reactivity in depth.
2. You are using a computed property. Computed properties should just return a value and should not modify anything. So to add a property toggleStatus
to contentObject
make use of created lifecycle hook.
So here are the changes:
var app2 = new Vue({
el: "#app2",
data: {
contentObject: {}
},
created() {
this.$set(this.contentObject, "toggleStatus", false);
},
methods: {
toggle: function() {
this.contentObject.toggleStatus = !this.contentObject.toggleStatus;
}
}
});
Here is the working fiddle
Upvotes: 1
Reputation: 17621
It doesn't work in second case first because in your computed property you always assign false to it.
contentObject.toggleStatus = false;
And secondly you are looking for Vue.set/Object.assign
var app1 = new Vue({
el: "#app1",
data: {
contentObject: {
toggleStatus: false
}
},
computed: {
content: function(){
var contentObject = this.contentObject;
return contentObject;
}
},
methods: {
toggle : function(){
this.contentObject.toggleStatus = !this.contentObject.toggleStatus;
}
}
})
var app2 = new Vue({
el: "#app2",
data: {
contentObject: {
}
},
computed: {
content: function(){
var contentObject = this.contentObject;
return contentObject;
}
},
methods: {
toggle : function(){
this.$set(this.contentObject, 'toggleStatus', !(this.contentObject.toggleStatus || false));
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app1">
current toggle status: {{content.toggleStatus}}<br/>
<button @click="toggle">Toggle (working)</button>
</div>
<div id="app2">
current toggle status: {{content.toggleStatus}}<br/>
<button @click="toggle">Toggle (not working)</button>
</div>
Upvotes: 1