Reputation: 1868
I am having trouble with applying filters whilst using checkboxes to a list of results and need some help.
Currently, only the 'All' option seems to apply any filtering logic.
My HTML containing my filters and loop is as follows:
<div class="container" id="clubs">
<div class="filter">
<label><input type="checkbox" v-model="selectedCategory" value="All" /> All</label>
<label><input type="checkbox" v-model="selectedCategory" value="Parking" /> Parking</label>
<label><input type="checkbox" v-model="selectedCategory" value="Toilets" /> Toilets</label>
<label><input type="checkbox" v-model="selectedCategory" value="Floodlights" /> Floodlights</label>
</div>
<ul class="clubs-list">
<li v-for="club in filteredClubs">{{ club.clubName }}</li>
</ul>
</div>
Then, the code inside my VueJS app is as below:
var vm = new Vue({
el: "#clubs",
data: {
clubs: [
{ clubName: "Club One", clubParking: true, clubToilets: false, clubFloodlights: true },
{ clubName: "Club Two", clubParking: true, clubToilets: false, clubFloodlights: false },
{ clubName: "Club Three", clubParking: false, clubToilets: true, clubFloodlights: true },
],
selectedCategory: "All"
},
computed: {
filteredClubs: function() {
var vm = this;
var category = vm.selectedCategory;
if(category === "All") {
return vm.clubs;
} else {
return vm.clubs.filter(function(club) {
return club.clubParking === category;
});
}
}
}
});
Any help welcome as I have been stuck for hours.
Upvotes: 0
Views: 94
Reputation: 29081
You need to update your filter to check the category, then filter on the field.
return vm.clubs.filter(function(club) {
switch(category){
case 'Toilets':
return club.clubToilets;
case 'Parking':
return club.clubParking;
// etc...
}
});
You can refactor this a bit by setting a field name.
return vm.clubs.filter(function(club) {
let fname;
switch(category){
case 'Toilets':
fname ='clubToilets';
case 'Parking':
fname = 'clubParking';
// etc...
}
return club[fname]
});
You can also simply have the value of the select be your field name and use it directly. This may restrict you from additional logic however.
<label><input type="checkbox" v-model="selectedCategory" value="clubParking" /> Parking</label>
return vm.clubs.filter(function(club) {
return club[category];
}
The bottom line is the category must be mapped to a field name in your object.
// Map the field names depending on your checkbox values. `selectedCategory` should be an array.
const selectedFieldNames = selectedCategory.map(category=>{
switch(category){
case 'Toilets':
return 'clubToilets';
case 'Parking':
return 'clubParking';
// etc...
}
})
// selectedFieldNames now contains the names of your object fields
// This will now return all items that have all those fields set to 'true'
return vm.clubs.filter(function(club) {
return selectedFieldNames.every(fname=>club[fname])
}
Note: This really could use some cleaning up, but I left it in a format that you can compare your work and ours.
var vm = new Vue({
el: "#clubs",
data: {
clubs: [
{
clubName: "Club One",
clubParking: true,
clubToilets: false,
clubFloodlights: true
},
{
clubName: "Club Two",
clubParking: true,
clubToilets: false,
clubFloodlights: false
},
{
clubName: "Club Three",
clubParking: false,
clubToilets: true,
clubFloodlights: true
}
],
selectedCategory: []
},
computed: {
filteredClubs: function() {
var vm = this;
var categories = vm.selectedCategory;
if (categories.includes("All")) {
return vm.clubs;
} else {
const selectedFieldNames = categories.map(category => {
switch (category) {
case "ClubToilets":
return "clubToilets";
case "ClubParking":
return "clubParking";
case "ClubFloodlights":
return "clubFloodlights";
}
});
return vm.clubs.filter(function(club) {
return selectedFieldNames.every(fname=>club[fname])
})
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container" id="clubs">
<div class="filter">
<label><input type="checkbox" v-model="selectedCategory" value="All" /> All</label>
<label><input type="checkbox" v-model="selectedCategory" value="ClubParking" /> Parking</label>
<label><input type="checkbox" v-model="selectedCategory" value="ClubToilets" /> Toilets</label>
<label><input type="checkbox" v-model="selectedCategory" value="ClubFloodlights" /> Floodlights</label>
</div>
<ul class="clubs-list">
<li v-for="club in filteredClubs">{{ club.clubName }}</li>
</ul>
</div>
Upvotes: 1