0
votes

I have a vueJs component which looks like the following:

export default {
  name: 'componentname',
  data () {
    return {
      items: []
    }
  },
  mounted() {
    this.getItems();
  },
  methods: {
    getItems() {
      this.$http.get('HTTP_API_ADDRESS').then(res => {
        this.items = res.data;
      })
    }
  }
}

I am using in my template a v-for loop on the items in the items array which appear after the call is made to my API.

I have a problem in that the objects in the array contain a boolean which I'm trying to update on page via a click but the object doesn't appear to update on page unless something which was explicitly defined in the instance is updated.

Example, purely an example - code isn't logical.

<ul>
  <li v-for="item in items" @click="item.available = !item.available">{{ item.name }} | {{ item.available }}</li>
</ul>

The idea is that the available would display true or false depending on the click for the item.

I believe its to do with the elements of the objects not being defined on mount however I'm unsure how I would do this if they are in an array?

2
I don't think it will not work. I have checked with a demo and your code is working fine. Please once moreNarendra Jadhav

2 Answers

0
votes

You could pre-populate available before the objects become reactive:

this.$http.get('HTTP_API_ADDRESS').then(res => {
  const items = res.data;

  for (const item of items) {
    item.available = false;
  }

  // The array and its objects are made reactive on the next line
  this.items = items;
})

Alternatively you can use $set to add a new property later:

@click="$set(item, 'available', !item.available)"

The relevant documentation is https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats.

0
votes

The way the vue (2.0) reactivity system works is with Object.defineProperty because of the way this works it will not work on nested properties only on primitive values. There ways to get around this, the simplest way is to make that property your boolean one a computed one like this:

computed: {
     booleanValue(){
        return this.myObject.someValue
    }
}

this code will now be reactive. Another solution is to use $set as suggested. Further more you can consider using the vue reactive internal api, see here and here