I read this documentation but cannot use the proposed solution.
I have a v-for
loop over objects. These objects are changed dynamically over time and I need that change to show reactively in the v-for loop.
<b-row lg="12" v-for="data in objects" :key="data.id">
<div v-if="data.loading">
loading...
{{data.loading}}
</div>
<div v-else>
loaded, done
{{data.loading}}
</div>
</b-row>
In my methods, I have a for loop that downloads data for each object and changes the object value like this:
for(var i = 0; i<response.ids.length; i++){
var newId = response.ids[i].id
this.objects.newId = {"loading":true, "id": newId}
downloadSomething(newId).then(res => {
this.objects.newId = res[0] //<-- this change needs to be shown reactively.
})
}
According to Vue documentation, Object changes are not reactive:
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` is now reactive
vm.b = 2
// `vm.b` is NOT reactive
Vue propses some workaround like this:
Vue.set(vm.userProfile, 'age', 27)
UPDATE
But for my case, this just creates a new parameter in the object with the same ID and creates a duplicate key warning and other problems.
I also tried Vue.delete
just before Vue.set but it is not actually deleting.
Is there a way to not replace the key/value pair but add more/change parameters to the first child of the root with the ID of newID
Thanks!
Vue3 v-model objects are not reactive.
To make it reactive we will use “reactive()” function; ##004 we can include also “computed properties” in the reactive object. You can access computed properties accessing to the object properties (game. total in this case);
Vue. set is a tool that allows us to add a new property to an already reactive object, and makes sure that this new property is ALSO reactive.
Solution: Replace this.objects.newId = res[0]
with this.$set(this.objects, 'newId', res[0])
and it should work.
Explanation: this.$set
is just an alias to Vue.set
, available within any Vue instance. Bear in mind that vm
(stands for view model) in the example is the same as this
and equals to Vue component instance. Also due to ES5 JS restrictions, you have to set objects' properties explicitly via Vue.set/this.$set
to manually trigger re-render. This problem will be resolved when Vue 3.0 is released.
Hope this helps, if you need any clarifications - feel free to ask.
Try that:
downloadSomething(newId).then(res => {
this.$set(this.objects, 'newId', res[0])
})
you need Vue.set()
when you want to define a new property to an existing object (not directly to the data), and this function will assign the new property to the built-in watcher, and it will become reactive as well.
its all being explained in the docs: https://v2.vuejs.org/v2/guide/reactivity.html
in your case, it seems to be all you need to make it work. in my example:https://jsfiddle.net/efrat19/eywraw8t/484131/ an async function fetches the data and define a new property to contain te response.
new Vue({
el: "#app",
data: {
objects:{
property1:12
}
},
methods: {
fetchDataAndAddProperty(response){
fetch('https://free.currencyconverterapi.com/api/v6/countries').then(res =>
res.json()).then(data => Vue.set(this.objects,'property2',data))
}
}
})
and the template:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
<div lg="12" v-for="(val,key,index) in objects" :key="index">
{{key}}:{{val}}
</div>
<button @click="fetchDataAndAddProperty()">fetch</button>
</div>
as you can see in the fiddle, the new property becomes reactive and being displayed as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With