How to implement a custom search with Vuejs

How to implement a custom search with Vuejs

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.

shot1.png

And when we search for a word, our app begins to filter

shot.png

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.