Eddie Weldon
Eddie Weldon

Reputation: 133

How to add a property to ALL objects in an array (data) using Vue.js?

Background: I have an array in data() that gets populated with objects from the backend. If the GET request retrieves 6 objects those 6 objects will update in the array.

Problem: I already understand vm.$set is needed to add properties to an object. But how do add properties to all object in the array?

I want to change:

 data() {
    return {
      expenseButton: [{key:value},{key:value},{key:value}]
         };
  }

to

data() {
    return {
      expenseButton: [{key:value, key2:value2},{key:value, key2:value2},{key:value, key2:value2}]
         };
  }

Failed attempt which logs newValue as a property in the array instead of each object

  methods: {
    check() {
      this.$set(this.expenseButton, "newValue", this.expenseButton.newValue);
      console.log(this.expenseButton);
    }
  },

UPDATE How to target all objects in an array via vm.$set so that all objects has a new property called "newValue"

 data() {
    return {
      expenseButton: [{key1:value1},{key2:value2},{key3:value3}]
         };
  }

TO

 data() {
    return {
      expenseButton: [{key1:value1,newValue: ''},{key2:value2, newValue: ''},{key3:value3, newValue: ''}]
         };
  }

Upvotes: 3

Views: 6359

Answers (2)

Cue
Cue

Reputation: 2759

You can use $set on arrays by passing the index at which you wish to set a new value.

However, since you're adding a new property to each item in the array, you could just map over the array items, add the property and replace the data item altogether which would be far more efficient.

check() {
  this.expenseButton = this.expenseButton.map((obj) => {
    obj.newValue = ''
    return obj
  })
}

To retain reactivity, you will need to invoke $set on each index with the corresponding key-value pair. See @blex's answer for reference.

check() {
  this.expenseButton.forEach((_, index) => {
    this.$set(this.expenseButton[index], 'newValue', '')
  })
}

If the above resolves your question, please accept @blex’s answer as your accepted solution.

Upvotes: 5

blex
blex

Reputation: 25648

You could use this.$set in a loop:

Vue.component('my-component', {
  template: '#my-component',
  data() {
    return {
      expenseButton: [{ key: 0 }, { key: 1 }, { key: 2 }]
    };
  },
  methods: {
    check() {
      this.expenseButton.forEach((o, i) => {
        this.$set(this.expenseButton[i], "key2", i * 2);
      });
    }
  }
});

var vm = new Vue({
  el: '#app'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.min.js"></script>

<div id="app">
  <my-component></my-component>
</div>

<template id="my-component">
  <div>
    <ul>
      <li v-for="x in expenseButton" :key="x.key">
       {{x}}
      </li>
    </ul>
    <button @click="check">Update items</button>
  </div>
</template>

Upvotes: 3

Related Questions