If you intend to display any form of data on your web application, then you'll probably need to allow users to be able to search through that data to find a desired item. This can be archived by implementing a custom search, and I will walk you through how to achieve this using Vuejs
and for this article, we'll be creating a simple app so we can learn by building.
Brief explanation of the app
I own a collection of books (do I?) I'll love to show off to my friends. So I'll like for them to search through because they might just want to find out how many of their favourite bestseller's books I own, just so they can judge my taste for books. So when a search word is entered, the app filters out books that do not contain the search term. Here's a link to the full source code on Codesandbox
We're getting started ...
Step 1: We begin by creating an array of the books in the App.vue
file.
App.vue
data() { return { books: [ { title: "A time to kill", author: "Josh Grisham" }, { title: "Greenlights", author: "Matthew McConaughey" }, { title: "The Da Vinci code", author: "Dan Brown" }, { title: "Born a crime", author: "Trevor Noah" }, { title: "The artist way", author: "Julia Cameron" }, { title: "The hate you give", author: "Angie Thomas" }, { title: "Billy Summers", author: "Stephen King" }, { title: "The Kite Runner", author: "Khaled Hosseini" }, ], }; }
Each object in the array holds basic details to represent a book, which is the book title and book author.
Step 2: Let's create an input field, where the search word will be entered into. We'll use the v-model
directive to create a two-way data binding on the form input.
App.vue
<div id="app"> <input v-model="search" placeholder="search for book by title or arthur" /> </div>
We'll also declare the initial value of the v-model
inside the data options of our App.vue
file by adding this simple line. This will automatically be updated as changes are made to the value of the input field
App.vue
search: ""
Step 3: Next, we write a function to filter out books that do not have the search term in them. This function will be written as a computed property because we'll simply be composing the data we care for from the existing data, without creating anything new.
App.vue
computed: { searchResults() { return this.books.filter( (books) => books.title.toLowerCase().includes(this.search.toLowerCase()) || books.author.toLowerCase().includes(this.search.toLowerCase()) ); }, }
This block converts each book title or name of the author into lowercase, before checking if it includes the search word which has also been converted to lower case. Without converting to lower case first, Vue will apply case sensitivity.
The or
symbol allows a book to be filtered on the basis of a matching title or matching name of the author.
Using javascript filter
, we select all items in the array that includes
the word entered in the input field.
Step 4: We'll use v-for
to loop over all objects in the searchResults
array which we have already created as a computed property, passing each object to the bookCard component as a prop.
Also, we'll create a component, which we'll call bookCard.vue
. As the name suggests, this component will display each book on a card. Then we'll pass each object in the v-for
loop (result in searchResults
) into the bookCard
component as a prop (result
).
Adding these to what we previously had in our App.vue
, we get
App.vue
<template> <div id="app"> <input v-model="search" placeholder="search for book by title or arthur" /> <div v-for="result in searchResults" :key="result.title"> <bookCard :book="result" :search="search" /> </div> </div> </template>
Step 5: Next, we receive the prop we had passed from our App.vue
as results
into our bookCard
component as book
bookCard.vue
export default { props: { Book: Object, }
Step 6: But our bookCard
component currently displays nothing, as our component has no HTML. So we'll access the content received in the prop and then render them using moustache notations.
bookCard.vue
<template> <div> <div class="book-container"> <h2>{{ book.title }}</h2> <small>by {{ book.author }}</small> </div> </div> </template>
Now we'll get a display of each book in our browser. Without searching for any word, we'll get a display of all books in our array, this is because our v-model
's value was initialized as an empty string.
And when we search for a word, our app begins to filter
Feel free to add your own styles to get a nicer look.
I'll be in the comment section, in case you have any questions, I'll be happy to attend to them.