Ari
Ari

Reputation: 6159

Mutating a value in vue when the key didn't previously exist does not update the view

I have a table and a select box for each row. I want the check box to model a value in the data that doesn't actually exist, yet.

<tr v-for="item in someData">
    <input type="checkbox" v-model="item.selected"></td>
    <input type="checkbox" v-model="item.name"></td>
<tr>

My data when loaded from the DB looks like this:

someData: [
    {'name': 'john'},
    {'name': 'kate'},
    {'name': 'aaron'},
]

When the user presses a Select All button it should update the selected key even if it doesn't exist (well thats the idea)

toggleSelect: function () {
this.someData.forEach(element => {
        element.selected = !element.selected;
    });
}

However the checkboxes don't react even though the values have been updated. To make this work I need to get the data and add the key/value manually prior to loading it into view and rendering

getDatabaseData: function () {
// some code omitted
    response['data'].forEach(element => {
        element["selected"] = false;
    });
    app.someData = response['data']
}

Am I doing it correctly? Am I right in thinking Vue won't be reactive to values that didn't exist prior to rendering?

Upvotes: 0

Views: 173

Answers (2)

David Porcel
David Porcel

Reputation: 290

You should be using Vue.set to update the value of the selected property on your objects in order to be reactive, like this:

import Vue from 'vue';
...
toggleSelect: function () {
    this.someData.forEach(element => {
        Vue.set(element, 'selected', !element.selected);
    });
}

Upvotes: 1

Kenneth
Kenneth

Reputation: 2993

Try this idea,

in vue component.

<input type="checkbox" v-model="selectAll"> Select All
   <tr v-for="item in someData" :key="item.name">
      <td>
         <input type="checkbox" v-model="selected" :value="item.name">
      </td>
   {{ item.name }}
</tr>

script:

data() {
        return {
            selectAll: false,
            selected: [],
            someData: [{ name: "john" }, { name: "kate" }, { name: "aaron" }]
        };
    },
    watch: {
        selectAll(value) {

            // validate if value is true
            if (value) {
                this.someData.forEach(item => {
                   // push unique value
                   if(this.items.indexOf(item.name) === -1) {
                       this.selected.push(item.name);
                   }
                });
            } else {
                // Unselect all
                this.selected = [];
            }
        }
    }

You have a selected variable where the selected Items are located. selectAll variable to select all items and push to selected variable.

Upvotes: 2

Related Questions