Jenssen
Jenssen

Reputation: 1871

Vue.js select all input fields

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?

Upvotes: 2

Views: 2776

Answers (4)

Richard Matsen
Richard Matsen

Reputation: 23483

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>

Upvotes: 1

Roy J
Roy J

Reputation: 43899

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

Upvotes: 1

David A
David A

Reputation: 413

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>

Upvotes: 1

Ryos
Ryos

Reputation: 396

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>

Upvotes: 1

Related Questions