📅 3 years ago 🕒 8 min read 🙎♂️ by Madza
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.
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.
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.
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.
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.
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.
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.
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:
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.