JavaScript autocomplete with API for input fields

Enabling autocomplete functionality in input fields through JavaScript can significantly enhance the user experience by providing real-time suggestions as they type. This feature streamlines the user’s interaction, allowing them to effortlessly choose from a set of options and minimizing the need for extensive keystrokes.

In this Answer, we break down the steps to implement an autocomplete feature on an input field in JavaScript by using an API call, and we’ll give a list of suggestions. For this example, we consider an input field for the user’s favorite fruit.

Step 1: Setting up a Node server

The first step is to create a node server that will be used as a backend server, and when we make an API call from the client side, it will respond.

const express = require('express');
const cors = require('cors'); // Add this line
const app = express();
const port = 3000;
const fruits = ['Abiu', 'Açaí', 'Acerola', 'Akebi', 'Ackee', 'African Cherry Orange', 'American Mayapple', 'Apple', 'Apricot', 'Araza', 'Avocado', 'Banana', 'Bilberry', 'Blackberry', 'Blackcurrant', 'Black sapote', 'Blueberry', 'Boysenberry', 'Breadfruit', 'Buddhas hand (fingered citron)', 'Cactus pear', 'Canistel', 'Cashew', 'Cempedak', 'Cherimoya (Custard Apple)', 'Cherry', 'Chico fruit', 'Cloudberry', 'Coco De Mer', 'Coconut', 'Crab apple', 'Cranberry', 'Currant', 'Damson', 'Date', 'Dragonfruit (or Pitaya)', 'Durian', 'Egg Fruit', 'Elderberry', 'Feijoa', 'Fig', 'Finger Lime (or Caviar Lime)', 'Goji berry', 'Gooseberry', 'Grape', 'Raisin', 'Grapefruit', 'Grewia asiatica (phalsa or falsa)', 'Guava', 'Hala Fruit', 'Honeyberry', 'Huckleberry', 'Jabuticaba (Plinia)', 'Jackfruit', 'Jambul', 'Japanese plum', 'Jostaberry', 'Jujube', 'Juniper berry', 'Kaffir Lime', 'Kiwano (horned melon)', 'Kiwifruit', 'Kumquat', 'Lemon', 'Lime', 'Loganberry', 'Longan', 'Loquat', 'Lulo', 'Lychee', 'Magellan Barberry', 'Mamey Apple', 'Mamey Sapote', 'Mango', 'Mangosteen', 'Marionberry', 'Melon', 'Cantaloupe', 'Galia melon', 'Honeydew', 'Mouse melon', 'Musk melon', 'Watermelon', 'Miracle fruit', 'Momordica fruit', 'Monstera deliciosa', 'Mulberry', 'Nance', 'Nectarine', 'Orange', 'Blood orange', 'Clementine', 'Mandarine', 'Tangerine', 'Papaya', 'Passionfruit', 'Pawpaw', 'Peach', 'Pear', 'Persimmon', 'Plantain', 'Plum', 'Prune (dried plum)', 'Pineapple', 'Pineberry', 'Plumcot (or Pluot)', 'Pomegranate', 'Pomelo', 'Purple mangosteen', 'Quince', 'Raspberry', 'Salmonberry', 'Rambutan (or Mamin Chino)', 'Redcurrant', 'Rose apple', 'Salal berry', 'Salak', 'Sapodilla', 'Sapote', 'Satsuma', 'Shine Muscat or Vitis Vinifera', 'Sloe or Hawthorn Berry', 'Soursop', 'Star apple', 'Star fruit', 'Strawberry', 'Surinam cherry', 'Tamarillo', 'Tamarind', 'Tangelo', 'Tayberry', 'Ugli fruit', 'White currant', 'White sapote', 'Ximenia', 'Yuzu'];
app.use(cors()); // Enable CORS
app.use(express.json());
app.get('/autocomplete', (req, res) => {
const query = req.query.query.toLowerCase();
const matchingFruits = fruits.filter(fruit => fruit.toLowerCase().includes(query));
res.json(matchingFruits);
});
app.listen(port,'0.0.0.0',() => {
console.log(`Server is running on http://0.0.0.0:${port}`);
});
  • Lines 1–2: We import all the required modules to use in our application.

  • Line 6: We define an array with the name of fruits, which includes a list of the fruit’s names.

  • Lines 12–16: We define a route that handles GET requests to /autocomplete. It filters a list of fruits based on a lowercase query parameter and responds with the matching fruits in JSON format.

Step 2: Adding HTML

The second step is to create the input field we use. We must also create a container that encapsulates the input field and the list of suggestions.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Autocomplete Example</title>
<!-- Styling for the autocomplete suggestions -->
<style>
/* Styles for the suggestions container */
#suggestions {
position: absolute;
background-color: #f1f1f1;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ccc;
}
/* Styles for each suggestion item */
#suggestions div {
padding: 10px;
border-bottom: 1px solid #ccc;
}
/* Hover effect for suggestion items */
#suggestions div:hover {
background-color: #ddd;
}
</style>
</head>
<body>
<!-- Autocomplete Example Header -->
<h2>Autocomplete Example</h2>
<!-- Input field for autocomplete -->
<input type="text" id="input">
<!-- Container for displaying autocomplete suggestions -->
<div id="suggestions"></div>

Lines 8–28: This section contains CSS styling the autocomplete suggestions. It defines the appearance of the suggestion container, individual suggestion items, and a hover effect for improved user interaction.

Lines 32–36: We defined the visible content of the web page as a h2 headingAutocomplete Examplethat will reflect on the upper side of the page and an input field of text the type where the user will add its query.

Step 3: JavaScript logic

In the third section, we’ll include JavaScript logic in our application that will help in processing our query.

<script>
// Function to implement autocomplete
function autocomplete(input) {
// Event listener for input changes
input.addEventListener('input', function () {
// Close the existing suggestions list
closeList();
// If the input is empty, do nothing
if (!this.value) return;
// Create a suggestions <div> and add it to the element containing the input field
const suggestions = document.createElement('div');
suggestions.setAttribute('id', 'suggestions');
this.parentNode.appendChild(suggestions);
// Fetch data from the Node.js server based on the input value
fetch(`{{EDUCATIVE_LIVE_VM_URL}}:3000//autocomplete?query=${encodeURIComponent(this.value)}`)
.then(response => response.json())
.then(data => {
// Iterate through the API response and create suggestion elements
data.forEach(item => {
const suggestion = document.createElement('div');
suggestion.innerHTML = item;
// Event listener for suggestion click
suggestion.addEventListener('click', function () {
input.value = this.innerHTML;
closeList();
});
suggestion.style.cursor = 'pointer';
suggestions.appendChild(suggestion);
});
})
.catch(error => {
console.error('Error fetching data from the server:', error);
});
});
// Function to close the suggestions list
function closeList() {
const suggestions = document.getElementById('suggestions');
if (suggestions) suggestions.parentNode.removeChild(suggestions);
}
}
// Initialize autocomplete for the specified input element
autocomplete(document.getElementById('input'));
</script>
  • Lines 3–15: We’ve defined a autocomplete function that accepts the user input as an argument. It utilizes an event listener addEventListener to respond to changes in the input. The function ensures that any previously open suggestion lists are closed and creates a fresh suggestion container (<div>), and then adds it to the input field’s parent element. If the user input is empty, the function performs no additional actions.

  • Lines 18–39: We made an API call with the help of fetched autocomplete suggestions from a Node.js server based on the user’s input. It handles the server response by iterating through the API response, creating suggestion elements for each item.

  • Lines 42–46: We defined the closeList() function. It retrieves the suggestions element and removes it if it exists.

Code

Now let’s explore our complete code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Autocomplete Example</title>
  <style>
    #suggestions {
      position: absolute;
      background-color: #f1f1f1;
      max-height: 150px;
      overflow-y: auto;
      border: 1px solid #ccc;
    }

    #suggestions div {
      padding: 10px;
      border-bottom: 1px solid #ccc;
    }

    #suggestions div:hover {
      background-color: #ddd;
    }
  </style>
</head>
<body>

<h2>Autocomplete Example</h2>
<input type="text" id="input">
<div id="suggestions"></div>

<script>
  function autocomplete(input) {
    input.addEventListener('input', function () {
      closeList();

      if (!this.value) return;

      // Create a suggestions <div> and add it to the element containing the input field
      const suggestions = document.createElement('div');
      suggestions.setAttribute('id', 'suggestions');
      this.parentNode.appendChild(suggestions);

      // Fetch data from the Node.js server based on the input value
      fetch(`{{EDUCATIVE_LIVE_VM_URL}}:3000//autocomplete?query=${encodeURIComponent(this.value)}`)
        .then(response => response.json())
        .then(data => {
          // Iterate through the API response and create suggestion elements
          data.forEach(item => {
            const suggestion = document.createElement('div');
            suggestion.innerHTML = item;

            suggestion.addEventListener('click', function () {
              input.value = this.innerHTML;
              closeList();
            });

            suggestion.style.cursor = 'pointer';
            suggestions.appendChild(suggestion);
          });
        })
        .catch(error => {
          console.error('Error fetching data from the server:', error);
        });
    });

    function closeList() {
      const suggestions = document.getElementById('suggestions');
      if (suggestions) suggestions.parentNode.removeChild(suggestions);
    }
  }

  autocomplete(document.getElementById('input'));
</script>

</body>
</html>
Complete code

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved