Vuejs and Vue.Set(), Update Array

Vuejs and Vue.set(), update array

VueJS can't pickup your changes to the state if you manipulate arrays like this.

As explained in Common Beginner Gotchas, you should use array methods like push, splice or whatever and never modify the indexes like this a[2] = 2 nor the .length property of an array.

new Vue({  el: '#app',  data: {    f: 'DD-MM-YYYY',    items: [      "10-03-2017",      "12-03-2017"    ]  },  methods: {
cha: function(index, item, what, count) { console.log(item + " index > " + index); val = moment(this.items[index], this.f).add(count, what).format(this.f);
this.items.$set(index, val) console.log("arr length: " + this.items.length); } }})
ul {  list-style-type: none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script><div id="app">  <ul>    <li v-for="(index, item) in items">      <br><br>      <button v-on:click="cha(index, item, 'day', -1)">      - day</button> {{ item }}      <button v-on:click="cha(index, item, 'day', 1)">      + day</button>      <br><br>    </li>  </ul></div>

Vuejs - update array of an object which is in an array

I could update the stages reactively. Here is my full code; I used the push method of an array object and it works:

<template>
<div>
<li v-for="item in stages" :key="item.stageId">
{{ item }}
</li>
</div>
</template>

<script>
export default {
data() {
return {
stages: [],
};
},
methods: {
async getTeamStages() {
this.stages = [{ stageId: 1 }, { stageId: 2 }];
for (let stage of this.stages) {
this.$set(stage, "tickets", []);
}
for (let stage of this.stages) {
await this.getStageTickets(stage);
}
},
async getStageTickets(stage) {
const tickets = ["a", "b", "c"];
for (let ticket of tickets) {
this.stages[this.stages.indexOf(stage)].tickets.push(ticket);
}
},
},
mounted() {
this.getTeamStages();
},
};
</script>

It should be noted that I used the concat method of an array object and also works:

this.stages[this.stages.indexOf(stage)].tickets = this.stages[this.stages.indexOf(stage)].tickets.concat(tickets);

I tried your approaches some of them work correctly:

NOT WORKED

this.$set(this.stages[this.stages.indexOf(stage)].tickets, tickets)

WORKED

this.$set(this.stages[this.stages.indexOf(stage)].tickets, 0, tickets[0]);

WORKED

  stage.tickets = tickets
this.stages.splice(this.stages.indexOf(stage), 1, stage)

I'm sure it is XY problem..

Vuejs and Vue.set(), update an Key/Value array

Since the edit properties in your rows objects are already set, you do not need to use Vue.set in this case. You can just set the property value and Vue will notice the change:

this.rows[0].edit = false;

Here's a simple example:

new Vue({
el: '#app',
data() {
return {
rows:[
{ "id": "4", "edit": true },
{ "id": "5", "edit": false }
],
}
},
methods: {
editNext() {
let index = this.rows.findIndex(r => r.edit);

this.rows[index].edit = false;

let next = ++index % this.rows.length;
this.rows[next].edit = true;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<div v-for="(row, i) in rows" v-if="rows[i].edit">
Editing Row ID {{ row.id }}
</div>

<button @click="editNext">Edit Next</button>
</div>

Vue.js Update Array not working using this.$set

I found the problem, Actually the property ListItem1 was not in the original Json so vue was not recognizing. what I did was use vue.$set correctly, was using Wrong

both work

this.$set(proj,"ListItem1",response.data.value);
Vue.set(proj,"ListItem1",response.data.value);

vue.js best way to update entire array

As suggested I will repond to this myself to help anyone in the same predicament.

oldArr = newArr

should still work (thank you choasia. Even though it is somewhat unclear in the vue.js documentation. Replacing the entire array will not fall under the caveats mentioned there (thank you Roy J ).

One option might also be to to empty the array and then push the new one like:

yourArray.push(... yourNewArray)

Thank you reiner

Array of objects - correct way of updating an object within the Vue.js ecosystem

This is a limitation of Vue's reactivity regarding arrays.

See #2 of Why isn’t the DOM updating?

When you modify an Array by directly setting an index (e.g. arr[0] = val) or modifying its length property. Similarly, Vue.js cannot pickup these changes. Always modify arrays by using an Array instance method, or replacing it entirely. Vue provides a convenience method arr.$set(index, value) which is syntax sugar for arr.splice(index, 1, value)

You can solve this by using Vue.set or Array.splice in your module:

import Vue from 'vue'

// find the block's index in the array
const index = state.contentBlocks.findIndex(block => block.id === contentBlock.id)

// using Vue.set
Vue.set(state.contentBlocks, index, contentBlock)

// using Array.splice
state.contentBlocks.splice(index, 1, contentBlock)

Updates to object inside array do not trigger updates

First things first.

Using Vue.set isn't going to help. Vue.set is used to set the values of properties that Vue's reactivity system can't track. That includes updating arrays by index or adding new properties to an object but neither of those apply here. You're updating an existing property of a reactive object, so using Vue.set won't do anything more than setting it using =.

Next...

Vue does not take copies of your objects when passing them as props. If you pass an object as a prop then the child component will get a reference to the same object as the parent. A deep watcher will trigger if you update a property within that object but it's still the same object. The old and new values passed to the watcher will be the same object. This is noted in the documentation:

https://v2.vuejs.org/v2/api/#vm-watch

Note: when mutating (rather than replacing) an Object or an Array, the old value will be the same as new value because they reference the same Object/Array. Vue doesn’t keep a copy of the pre-mutate value.

As you've noticed, one solution is to use a totally new object when performing the update. Ultimately, if you want to compare the old and new objects then you have no choice but to make a copy of the object somewhere. Taking a copy when mutating is a perfectly valid choice, but it's not the only option.

Another option would be to use a computed property to create the copy:

new Vue({
el: '#app',

data () {
return {
params: {
name: 'Lisa',
id: 5,
age: 27
}
}
},

computed: {
watchableParams () {
return {...this.params}
}
},

watch: {
watchableParams (newParams, oldParams) {
console.log(newParams, oldParams)
}
}
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
<input v-model="params.name">
<input v-model="params.id">
<input v-model="params.age">
</div>

VueJS2 : Push items into array and only update if property has changed

You have to assign the values of the object instead of pushing to array when the object is already in array.

language(x) {
// this.formValues.push(x);
let el = this.formValues.find((e) => e.P_uniqueID === x.P_uniqueID);
if (el) {
Object.assign(el, x);
} else {
this.formValues.push(x);
}

this.$emit("languages", this.formValues);
}

Working codesandbox



Related Topics



Leave a reply



Submit