Tips for implementing an autocomplete/suggestion search bar using VueJS

While working on a full-stack application using the MEVN stack, I am aiming to allow users to search for cards. As they type in the search bar, my goal is to display a dropdown list of options that narrows down with each character entered.

Although I have figured out how to filter the list using computed/watch properties, I am struggling with displaying the list as the user types, similar to the image below:

The approach I can think of involves using v-model on a ul element, but I'm not sure if it is the most efficient method. Most resources I found address similar issues with the select element, which is not what I desire.

I envision something along the lines of this picture:

https://i.sstatic.net/baHSd.png

Answer №1

Recently, I had to develop a similar feature using Vue.js. To achieve this, I utilized a list (ul) to display the search results. Essentially, I implemented a watcher to monitor changes in the search term (with debouncing to prevent overwhelming the server with requests for every keystroke), and then called an API that returned the relevant results stored in a component property (specifically, within the component's data).

The basic structure looked something like this:

<template>
 <div>
  <div><input type="text" v-model="searchString"/></div>
 </div>
 <div>
  <ul>
   <li v-for="result in results" :key="result.id">{{ result.label }}</li>
  </ul>
 </div>
</template>

<script>
import { debounce } from "lodash";
import axios from "axios";

export default {
   name: "SearchThingy",
   data: function() {
     return {
        searchString: "",
        results: []
     }
   },
   watch: {
      searchString: debounce(function () {
        this.search();
      }, 1000),
   },
   methods: {
      search: function() {
         axios.get(`/search?query=${this.searchString}`)
           .then((response) => this.results = response.data.results);
      }
   }
};
</script>

I didn't conduct any tests on this code, but hopefully, it serves as a good starting point for you, considering the broad nature of your initial question.

Answer №2

Have you heard of MEVN? It involves using MongoDB for your database needs. To start off, it's essential to create an API search endpoint that functions like this:

//search.js

import User from "../models/user";
export default async function(req, res) {
   let query = req.body.query;

   if (!query) {
     return res.status(200).json([]);
   }
   const users = await User.aggregate([
     {
       $searchBeta: {
         search: {
           query,
           path: ["name", "surname"],
           phrase: {
             prefix: true
           }
         }
       }
     }
   ]);

   return res.status(200).json(users);
 }

Let me break down the aggregation pipeline for you. Initially, you need to import your mongoose schema (if you're using mongoose). The key here is the $searchBeta stage. This stage conducts a full-text search on designated fields. In my scenario, I'm searching for users based on their names and surnames, looking for any relevant matches. The setting is such that the phrase parameter is set to prefix=true, enabling instant results with just one character input.

The resulting Array returned by the API endpoint will contain documents matching the criteria, sorted by a searchScore.

In your frontend implementation, consider something along these lines:

<template>
  <div class="searchbox">
     <input
       @keyup="search"
       placeholder="Search..."
       type="text"
       v-model="query"
    />
    <div
      class="result"
      v-for="result in matchArray"
      :key="result._id"
    >
      <div class="account_box">
        <i class="far fa-user"></i>
      </div>
      <p>{{ result.name + " " + result.surname }}</p>
    </div>
  </div>
</template>

<script>
export default {
   data(){
      return {
         query: "",
         matchArray: []
      }
   },
   methods: {
      axios.post("/api/search", {
         query: this.query:
      })
      .then(res => {
         matchArray = res.data;
      });
   }
}
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Understanding Variable Scope in JavaScript: How Variables are Accessed in Different Functions

I've been experimenting with a script that utilizes jQuery's get function to transfer data to another page and display the returned information as an alert on the current page. My goal is to send both the search field value from an input form (wh ...

PayPal Integration with React for Seamless Checkout Experience

I established a small and uncomplicated online store featuring a PayPal checkout system, and it is functioning adequately. Now, I am looking to include detailed information about the purchased products in the transaction history of my PayPal account. This ...

Merge the JSON data with the Node.js/Express.js response

Whenever I input somedomain.com/some_api_url?_var1=1 in a browser, the response that I receive is {"1":"descriptive string"}. In this JSON response, the index 1 can vary from 1 to n, and the "descriptive string" summarizes what the index represents. I am ...

Issue encountered when using Vue.js with the "calc(...)" attribute binding

Creating a vertical line in an SVG that adjusts its length based on the height of the containing SVG can be challenging, especially when dealing with responsive designs. One approach is to use a rect element with a width of 1px and a height of 100%, but po ...

I am unsuccessful in transferring the "side-panel content" to the side panel located on the main menu page

I am facing an issue where I want to pass My left and right Panel to the main menu page (dashboard), but it is not working as expected. The problem arises because the first page that needs to be declared is the login page (/ root) in my case. If I pass it ...

An error was returned by Ajax when attempting to make the ajax call

I have a custom ajax function that successfully updates my database. After the update, I call the successAlert() function. Now, I want to incorporate an error handling mechanism by calling the error function in case of any errors. However, during testing, ...

Having trouble loading Strapi 3 and Nuxt 2 on Localhost:1337/admin?

I'm currently running Nuxt version 2.15.8 and Node version v14.15.3. One of the modules I've installed is nuxtjs/strapi. In addition, I have incorporated the strapi v3 wrapper for nuxt 2 as outlined here. In my nuxt.config.js file, I am calling ...

Ways to reposition arrows upwards in Vuetify carousel

Looking for help on adjusting the position of arrows in a carousel made with vuetify. I need to move both arrows up by setting top:0 in both v-window__next and v-window__prev classes, but unsure how to apply this property to the component. https://i.sstat ...

Obtain the refined information from a UiGrid table

Is there a way to loop through the filtered rows in an uigrid? I am aware that we can get the filtered rows using the following code: var filteredData = $scope.gridApi.core.getVisibleRows($scope.gridApi.grid); However, I need to iterate through it and cr ...

How do I choose the specific financial date of April 1st in the datepicker selection?

I am trying to set the minimum date as 1st April 2018 and the maximum date as the current date. These are the methods I have already attempted: $("#primarySaleDatePicker").pickadate({ min: new Date(2018, 3, 1), max: 'today', ...

JavaScript objects inherit properties and methods from classes through prototypes

Looking to extend the functionality of the DataView object by creating a custom type and adding extra methods, but unsure of the correct approach. Attempted the following: var CustomDataView = function() { this.offset = 0; }; CustomDataView.prototype ...

Does vite handle module imports differently during development versus production?

I am currently working on incorporating the jointjs library into a Vue application. It is being declared as a global property in Vue and then modified accordingly. Below is a basic example of what I am trying to achieve: import Vue from 'vue'; im ...

Leveraging the Composition API in Vue 3: Implementing reusable code from a separate file into the template

I have developed a reusable code snippet in dateTime.js: import { ref, computed, watch } from 'vue'; import * as dayjs from 'dayjs'; export default function dateTime() { const newDateTimeString = ref(null); function showDateT ...

find the next earliest date in the array after the specified date

How can I find the smallest date in an array of dates that comes after a specific date? var datesArray = ['2019, 10, 4', '2019, 10, 13', '2019, 10, 8', '2019, 10, 6']; ownDate = '2019, 10, 05'; I need to ...

What is the process for associating JSON reponses with button actions on a webpage?

I developed a JavaScript script that interacts with a Tableau server API to handle running jobs. The script presents the retrieved jobs on a web page, along with corresponding buttons that enable users to terminate specific jobs. While the script function ...

Prevent overlap of plane geometry in Three.js

Within the scene, I have introduced both sphere and plane geometry elements using X and Y coordinates to position the plane geometry. Unfortunately, some of the plane geometries are overlapping each other, causing an issue that needs to be addressed. The g ...

The Carousel feature functions properly with 3 or more slides, but malfunctions when there are only 2 slides present

After implementing a minimal carousel, I discovered that it functions perfectly with 3 or more slides. However, as soon as I remove some slides, issues start to arise. Some of the problems I encountered include: The sliding animation is removed on ' ...

"Here's a cool trick: A guide on dynamically inserting a value into {% url tag %} using JavaScript within

Incorporating leaflet JS into a Django template, the aim is to display markers on a map where latitude and longitude are sourced from a queryset. Sending the queryset through views and utilizing the Django template language within <script> tags seeme ...

Checking for null values in a filter test in Javascript

Seeking guidance on how to implement null testing in my filter. The current setup works well unless any of the fields contain a "null" value. In such cases, an error is thrown: TypeError: Cannot read property 'includes' of null Thank you in adv ...

Adjust the size of the image based on its current dimensions, rather than its original dimensions

My goal is to scale an image with the ID "room" by a parameter of +1 or -1, which represents +-10% of the constant scaling factor. This is my current approach: function scalar(scaleP100){ /* scaleP100 ranges from +1 to -1 */ var addX ...