Dealing with lists is something you cannot avoid no matter the kind of application you’re building. With an ever growing list of records, you’re often left to deal with filters and sorters. Here, I’m going to show how to filter a list of data based on a selection from a drop down (select) menu.
Here’s the component code I’ve written to serve the purpose:
<template>
<div id="app">
<div class="np-category-select">
<label for="cars">Choose a category:</label>
<select
@change="updateList()"
name="category"
id="category"
class="np-category-select-input"
v-model="selectedCategory"
>
<option value="All">All</option>
<option value="Vegetable">Vegetable</option>
<option value="Fruit">Fruit</option>
</select>
</div>
<div class="np-list-item">
<div class="np-ib np-ib-item np-ib-item__head">ID</div>
<div class="np-ib np-ib-item np-ib-item__head">Title</div>
<div class="np-ib np-ib-item np-ib-item__head">Category</div>
</div>
<div v-for="(item, i) in sortedListItems" :key="i" class="np-list-item">
<div class="np-ib np-ib-item">
{{ item.id }}
</div>
<div class="np-ib np-ib-item">
{{ item.title }}
</div>
<div class="np-ib np-ib-item">
{{ item.category }}
</div>
</div>
<div class="np-credits">www.nightprogrammer.com</div>
</div>
</template>
<script>
import { listItems } from "./listItems";
export default {
name: "App",
data() {
return {
listItems: listItems,
sortedListItems: listItems,
selectedCategory: "All",
};
},
mounted() {
this.sortedListItems = this.listItems;
},
methods: {
updateList() {
this.sortedListItems = [];
this.sortedListItems =
this.selectedCategory === "All"
? (this.sortedListItems = listItems)
: listItems.filter((item) => item.category === this.selectedCategory);
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding: 12px 16px;
max-width: 430px;
}
.np-list-item {
border-bottom: 1px solid rgb(231, 231, 231);
}
.np-ib {
display: inline-block;
}
.np-ib-item {
min-width: 130px;
padding: 6px;
}
.np-ib-item__head {
font-weight: 600;
color: #0059ff;
}
.np-category-select {
margin: 4px 0px 20px 0px;
}
.np-category-select-input {
min-width: 120px;
margin-left: 10px;
outline: none;
border: 1px solid #0059ff;
font-size: 16px;
background: #0059ff;
color: #ffffff;
border-radius: 4px;
padding: 3px;
}
.np-credits {
font-size: 12px;
margin-top: 12px;
}
</style>
Code language: HTML, XML (xml)
I’ll explain the code in a bit, but you’d notice I’ve imported a file listItems.js on line 39. It basically contains some seed data which I used for the demonstration:
export const listItems = [
{
id: 0,
title: "Apple",
category: "Fruit"
},
{
id: 1,
title: "Mango",
category: "Fruit"
},
{
id: 2,
title: "Banana",
category: "Fruit"
},
{
id: 3,
title: "Spinach",
category: "Vegetable"
},
{
id: 4,
title: "Cucumber",
category: "Vegetable"
}
];
Code language: JavaScript (javascript)
Now, let’s move on to the component and understand how it’s working:
I’ve created a drop down menu on line 5, which calls the updateList() method. On line 54, I’ve emptied the rendered list first (sortedListItems), and then copied new data to it depending upon selection.
If the selectedCategory‘s value is ‘All‘, I’d copied all the data from the original list. Otherwise, I’d filter the data which only satisfies the expression on line 59.
It’s worth notifying that I’m clearing the renderable data, and filling it again on every selection change. I could’ve prevented it by creating two separate lists for two categories (or n lists for n categories). Or, I could modify the original list by copying the data from it into a temporary list. But in both the operations, there’d be bigger performance penalty or storage penalty.
You’d also notice that I’ve coped the original data from the file (listItems.js) into the listItems state on line 51.
This is how the view should appear like:
You can find a working version of the above example from our links below: