Home » vue » Vue reactivity doesn't pick up new property added to element in a array

Vue reactivity doesn't pick up new property added to element in a array

Posted by: admin November 26, 2021 Leave a comment

Questions:

Not sure if I am explaining this right, but I am facing an issue where one of my template elements isn’t reacting to added property of an array element. For example:

<div v-for="user in users"
     v-bind:key="user.id"
     v-bind:name="user.name">
     {{user.name}}
     <div class="warn" v-if="user.hasWarning">Warning!</div>
</div>

I am trying to display the warning whenever hasWarning: true is added to user

data:() {
  users: [
    {id: 1, name: "Foo"}
  ]
},
methods:{
  showWarning: function(id) {
    users.forEach(user => {
      if (user.id == id) {
        user.hasWarning = true;
      }
    });
  }
}

I tried calling showWarning(id) and I do see hasWarning added to user from both console and Vue developer tools, but it doesn’t render <div class class="warn" v-if="user.hasWarning"... If I have my user set up as {id: 1, name: "foo", hasWarning: false}, it seems to work fine, but why it is not working for added property? Should I avoid it entirely?

Answers:

You must to use the method this.$set to register new properties. See in documentation: https://vuejs.org/v2/api/#vm-set

Try something like that:

<template>
  <div>
    <div v-for="user in users" v-bind:key="user.id" v-bind:name="user.name">
      {{ user.name }}
      <button @click="showWarning(user.id)">showWarning</button>
      <div class="warn" v-if="user.hasWarning">Warning!</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    users: [{ id: 1, name: 'Foo' }, { id: 2, name: 'Bar' }],
  }),
  methods: {
    showWarning(id) {
      let user = this.users.find(user => user.id == id);
      this.$set(user, 'hasWarning', true);
    },
  },
};
</script>