2

I'm trying to select all input fields when I click the Select all names button but that's not working?

I've made a example:

new Vue({
    el: '#app',
    data: {
        names: [ 
            { "name": "one" },
            { "name": "two" },
            { "name": "three" }
        ]
    },
    created() {
         this.names.filter(name => name.checked = false);
    },
    methods: {
        selectAll() {
        		this.names.filter(name => name.checked = true);
        }
    }
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
    <table>
      <tr>
        <th>Names</th>
      </tr>
      
      <tr v-for="name in names">
        <td>
        <input type="checkbox" v-model="name.checked">{{name.name}}        </td>
      </tr>
  </table>
  
   <button @click="selectAll()">
        Select all names
   </a>
</div>

What am I doing wrong here?

4 Answers 4

1

You need to initialize checked in each element of your data.names array so that Vue knows that it exists. The below code should perform the intended behaviour correctly:

new Vue({
    el: '#app',
    data: {
        names: [ 
            { "name": "one", checked: false },
            { "name": "two", checked: false },
            { "name": "three", checked: false }
        ]
    },
    created() {
         this.names.filter(name => name.checked = false);
    },
    methods: {
        selectAll() {
            this.names.filter(name => name.checked = true);
        }
    }
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
    <table>
      <tr>
        <th>Names</th>
      </tr>
      
      <tr v-for="name in names">
        <td>
        <input type="checkbox" v-model="name.checked">{{name.name}}        </td>
      </tr>
  </table>
  
   <button @click="selectAll()">
        Select all names
   </a>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, but I get the names through an ajax call so how do I set the checked property correctly on the name object?
Then add checked to the results of the ajax call before assigning it to names.
1

As Roy said, Vue has a problem with adding new properties to existing objects, however you can work around this like so:

created () {
    this.names = this.names.map(name => Object.assign({}, name, { checked: false }));
}

new Vue({
    el: '#app',
    data: {
        names: [ 
            { "name": "one" },
            { "name": "two" },
            { "name": "three" }
        ]
    },
    created() {
        this.names = this.names.map(name => Object.assign({}, name, { checked: false }));
    },
    methods: {
        selectAll() {
        	this.names.filter(name => name.checked = true);
        }
    }
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
  <table>
    <tr>
      <th>Names</th>
    </tr>
      
    <tr v-for="name in names">
      <td>
      <input type="checkbox" v-model="name.checked">{{name.name}}        </td>
    </tr>
  </table>
  
  <button @click="selectAll()">
    Select all names
  </button>
</div>

Comments

1

Vue cannot detect property addition or deletion. Initialize checked in your data object so Vue can make it reactive.

Comments

1

I'll just throw in this variation, since from comments 'I get the names through an ajax call'

You can use a combination of Vue.set() and vm.$data to dynamically add to the names array after an ajax call returns.

Ref: Vue.set(target, key, value)

Set a property on an object. If the object is reactive, ensure the property is created as a reactive property and trigger view updates. This is primarily used to get around the limitation that Vue cannot detect property additions.

This doc says that target can't be the root data object of the instance, however Vue.set(vm.$data, 'names',... does work.

However, in case there is some unseen consequence names can be moved down a level.

console.clear()
const vm = new Vue({
    el: '#app',
    data: {
      data: {
        names: []
      }
    },
    mounted() {
      // setTimeout to simulate an ajax call
      setTimeout(() => {
        console.log(vm.$data)
        Vue.set(vm.$data.data, 'names', [ 
          {name: 'one', checked: false}, 
          {name: 'two', checked: false} 
        ]);
      }, 100);
    },
    methods: {
        selectAll() {
            this.data.names.filter(name => name.checked = true);
        }
    }
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
  <table>
    <tr>
      <th>Names</th>
    </tr>
      
    <tr v-for="name in data.names">
      <td>
      <input type="checkbox" v-model="name.checked">{{name.name}}        </td>
    </tr>
  </table>
  
  <button @click="selectAll()">
    Select all names
  </button>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.