How to Create a Search Bar in VueJS

📅 2 years ago 🕒 8 min read 🙎‍♂️ by Madza

How to Create a Search Bar in VueJS

The internet is a vast ocean of information. Search bars help us to filter the information and save time during the process.

Search bars are used in virtually every app or website from Google and Twitter to e-commerce stores and complex human, finance, and content management systems.

In this tutorial, we will be building a custom search bar in the VueJS, which is an awesome JavaScript framework for building fast and lightweight user interfaces.

Preview

What will we build?

Search bars come in many different shapes in forms. Today I will guide you through the steps of layout, logic, and styling on how you can create a search bar that filters an existing list of fruits.

In our case, there will not use any complex algorithm to process the search query, but we will use a simple function to filter out the result by the query the user enters.

To improve the UX the results will be returned in real-time, meaning they will be updated as the user types, with no need to click on anything to submit the search query to execute.

We will also track the scenarios, when there are no results for the search query, by returning an informative message to the user.

Set up the VueJS App

First, run npm init vue@latest in your terminal. This will execute create-vue which is an official scaffolding tool by VueJS to create fully-functional VueJS projects.

You will be asked to give your project a name in the terminal wizard. Let's call our app vue-search-app. When asked for further configuration of the project, press enter for all the options.

After that cd in your project by running cd vue-search-app and run npm install to set all the necessary dependencies for the project.

After that run npm run dev and it will start a dev server for your new VueJS app, which you can access by opening http://localhost:3000 in your browser.

Setup

Creating the component

Navigate to the src folder and find the App.vue file. We will write everything from scratch so make sure you first remove all the content from App.vue. Then include the following code:

<template>
   <input type="text" v-model="input" placeholder="Search fruits..." />
  <div class="item fruit" v-for="fruit in filteredList()" :key="fruit">
    <p>{{ fruit }}</p>
  </div>
  <div class="item error" v-if="input&&!filteredList().length">
     <p>No results found!</p>
  </div>
</template>

In VueJS, all the Single File Components must be wrapped in the template tag. VueJS is going to compile everything inside it into the Virtual DOM.

Next, we created the input field itself. We set the type to text, since we will be entering the search queries inside it. We also added a built-in directive v-model to it, that will allow us to create a two-way binding between the typed in value and data property. We also included a custom placeholder value, that hints the user to perform a search action.

Then we created the search items that will be returned. We used the built-in v-for directive to render a list of items in a paragraph based on a fruits array, that we will create in the next section. We also passed a :key attribute, which is a recommended practice when looping through elements in VueJS.

Finally, we created an error element, that will be displayed if there are no results for the search query. For this, we used the built-in v-if directive which will check whether there is an input typed in and no results from the filter function. If both conditions are satisfied, the element is rendered.

For both div elements we also included class attributes, so we can style them later. Both of them will contain the item class, while the fruit and error classes will be used to assign the different styling rules.

Adding the data and logic

In order to add data and logic to the component, we will write some JavaScript. VueJS allows us to write it in the same App.vue file, by wrapping it in the <script> tags.

Under the template tags we created previously, include the following code:

<script setup>
import { ref } from "vue";
let input = ref("");
const fruits = ["apple", "banana", "orange"];
function filteredList() {
  return fruits.filter((fruit) =>
    fruit.toLowerCase().includes(input.value.toLowerCase())
  );
}
</script>

We first included the setup in the opening <script> tag, which is a compile-time syntactic sugar introduced in VueJS version 3.2, that allows us to write code with less boilerplate.

Then we imported the ref attribute, which will let us store the user input in the search bar. We created a new variable input that will use the imported ref just for this cause.

Then we created the fruit array, that will hold the data we will loop through. Normally the data would come from the database, but for this tutorial, we will use simple dummy data.

Finally, we created filteredList function that will check the user input again each word in the fruits array and will return only those elements that include the search query.

If we check the browser, we should now be presented with functional search bar, that does not have any styling. We will work on it to make it pretty in the next sections.

Unstyled

Downloading the search icon

VueJS uses a very straightforward file structure to use assets in your projects. Inside src folder you will find the assets folder, where you can include the static assets you want to use. To access them simply provide the path from the file (like assets/image.svg from the App.vue).

In our app, we will use an SVG search icon to make the search input area more appealing to the eye and improve the UI, by highlighting that the input area is for search. You can download some nice search icons on sites like svgrepo.com or flaticon.com.

After download, rename it search-icon.svg and put it into assets folder.

Styling the component

We can do the styling in the App.vue file as well. The only requirement is that all the style rules must be wrapped inside <style> tags.

Under the <script> tags we created previously, include the following style rules:

<style>
@import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap");

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Montserrat", sans-serif;
}

body {
  padding: 20px;
  min-height: 100vh;
  background-color: rgb(234, 242, 255);
}

input {
  display: block;
  width: 350px;
  margin: 20px auto;
  padding: 10px 45px;
  background: white url("assets/search-icon.svg") no-repeat 15px center;
  background-size: 15px  15px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
    rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
}

.item {
  width: 350px;
  margin: 0 auto 10px auto;
  padding: 10px 20px;
  color: white;
  border-radius: 5px;
  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px,
    rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;
}

.fruit {
  background-color: rgb(97, 62, 252);
  cursor: pointer;
}

.error {
  background-color: tomato;
}
</style>

At the top of the style rules, we used import syntax to import the Montserrat font so we can use it in our search component. You can pick any from many alternatives in Google fonts, all of them are free.

Then we created custom reset rules for all the elements used in our app, so there are no default values for styling and the app looks the same on all the browsers. We got rid of default padding, margin, set the box-sizing to include padding and margin in the width and height as well as set each element to use the imported Montserrat font.

Then we set the body to take the entire height of the screen, added some padding to it, and set the background color to be a very light shade of blue.

For the input element we set the specific width, added some margin and padding, and set the font size. We used background property to set the background color, imported the search icon, and positioned it in the input field. We also removed the custom border, set the corners to be slightly rounded as well as added a nice shadow effect to the input.

For the returned elements we set a specific width and added some margin and padding. We set the corners to be slightly rounded and added a nice shadow effect. Also, we set the font color to be white.

Finally, we gave fruit and error elements some separate styling rules for the background color and we also set the cursor to turn into a pointer when hovering over fruit items.

The final demo

Now check if your dev server is still running in the terminal. If it is, visit the browser and open http://localhost:3000 again. If the server is not working, run the command npm run dev first.

You should be presented with a fully functional and designed search bar that lets you filter out the items as you write. Try to test it with truthy and faulty values to see it handles both cases:

Demo

Conclusion

In this tutorial, we created a fully functional search bar. We reviewed directive concepts like data binding, looping, conditional rendering, and using refs to store the input values provided by the user.

We also avoided any styling and component libraries, teaching you how you can create your own styling from scratch. We also learned how you can include your own icons in the input bar.

Hopefully, you learned something useful and next time you will work on a VueJS project you will know how to implement a search bar to help your users find the content they are looking for.