Reputation: 1871
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
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
Reputation: 43899
Vue cannot detect property addition or deletion. Initialize checked
in your data object so Vue can make it reactive.
Upvotes: 1
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
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