I am trying to create a query table with checkbox filter functionality. You can simply run the following code snippet to understand more easily.
When user ticks the checkboxes, the following table should be filtered accordingly.
Now, I have following questions:
How can I make all checkboxes are checked in default? (When user click "Search fruit", they can originally see all checkboxes are checked and all fruits are shown.) I tried to input
checked
attributed in the HTML, but it doesn't work.How to bind selected checkboxes with the following table to have a filter functionality? I tried to use
v-on:click
on each checkbox, but it seems not working...
The following is the simple code snippet:
new Vue({
el: '#app',
data: {
isSearched: false,
searchList: [],
data: [
{ "name": "apple", "color": "red" },
{ "name": "banana", "color": "yellow" },
{ "name": "strawberry", "color": "red" },
{ "name": "avocado", "color": "green" },
{ "name": "kiwi", "color": "green" },
],
selected: []
},
computed: {
colors() {
let colors = [];
this.searchList?.forEach(fruit => {
if(colors.indexOf(fruit.color) === -1){
colors.push(fruit.color);
}
});
return colors;
},
selectAll: {
get(){
return this.colors.length == this.selected.length;
},
set(value){
let selected = [];
if (value) {
this.colors.forEach(color => {
selected.push(color);
});
}
this.selected = selected;
}
}
},
methods: {
search() {
this.searchList = this.data;
this.isSearched = true;
}
}
});
table, td, th{
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="app">
<button @click="search">Search Fruit</button>
<br/><br/>
<div v-if="isSearched">
<table>
<tr>
<th colspan="2">Filter</th>
</tr>
<tr>
<th>
<input type="checkbox"
v-model="selectAll"
/>
</th>
<th align="left">All Color</th>
</tr>
<tr v-for="color in colors">
<td>
<input type="checkbox"
v-model="selected"
:value="color"
checked/>
</td>
<td>{{ color }}</td>
</tr>
</table>
<br/>
<table>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
<tr v-for="fruit in searchList">
<td>{{ fruit.name }}</td>
<td>{{ fruit.color }}</td>
</tr>
</table>
</div>
</div>
CodePudding user response:
The reason why checked
attribute does not work initially is here:
v-model will ignore the initial value, checked, or selected attributes found on any form elements. It will always treat the Vue instance data as the source of truth. You should declare the initial value on the JavaScript side, inside the data option of your component.
Therefore this.selected = [...this.colors];
is in search
method in the following code snippet. Also, searchList
is a computed property and colors
computed property has been changed for filter.
new Vue({
el: '#app',
data: {
isSearched: false,
data: [{
"name": "apple",
"color": "red"
},
{
"name": "banana",
"color": "yellow"
},
{
"name": "strawberry",
"color": "red"
},
{
"name": "avocado",
"color": "green"
},
{
"name": "kiwi",
"color": "green"
},
],
selected: []
},
computed: {
colors() {
let colors = [];
this.data.forEach(fruit => {
if (colors.indexOf(fruit.color) === -1) {
colors.push(fruit.color);
}
});
return colors;
},
selectAll: {
get() {
return this.colors.length == this.selected.length;
},
set(value) {
let selected = [];
if (value) {
this.colors.forEach(color => {
selected.push(color);
});
}
this.selected = selected;
}
},
searchList() {
const filteredList = [];
this.selected.forEach(color => {
this.data.forEach(x => {
if (x.color === color) {
filteredList.push(x);
}
});
});
return filteredList;
}
},
methods: {
search() {
this.isSearched = true;
this.selected = [...this.colors];
}
}
});
table,
td,
th {
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>
<div id="app">
<button @click="search">Search Fruit</button>
<br/><br/>
<div v-if="isSearched">
<table>
<tr>
<th colspan="2">Filter</th>
</tr>
<tr>
<th>
<input type="checkbox" v-model="selectAll" />
</th>
<th align="left">All Color</th>
</tr>
<tr v-for="color in colors">
<td>
<input type="checkbox" v-model="selected" :value="color" />
</td>
<td>{{ color }}</td>
</tr>
</table>
<br/>
<table>
<tr>
<th>Name</th>
<th>Color</th>
</tr>
<tr v-for="fruit in searchList">
<td>{{ fruit.name }}</td>
<td>{{ fruit.color }}</td>
</tr>
</table>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
</div>
</div>