How to Implement a Searchable Dropdown in JavaScript

Muhaymin Bin Mehmood

Muhaymin Bin Mehmood

· 8 min read
How to Implement a Searchable Dropdown in JavaScript Banner Image
How to Implement a Searchable Dropdown in JavaScript Banner Image

Introduction

A searchable dropdown is a common UI component that enhances user experience by allowing users to quickly find relevant options as they type. This is especially useful for large datasets, where manually scrolling through options is impractical.

In this tutorial, we’ll build a fully functional searchable dropdown in vanilla JavaScript without relying on external libraries. The dropdown will:

Filter options dynamically based on user input
Support large datasets efficiently
Fetch data from an API (e.g., JSONPlaceholder)
Handle performance optimizations for smooth rendering

By the end of this guide, you’ll have a scalable, reusable, and optimized searchable dropdown component for your web applications.

Table of Contents

1️⃣ Understanding Searchable Dropdowns
2️⃣ HTML & Basic Styling for the Dropdown
3️⃣ Implementing Search Logic with JavaScript
4️⃣ Handling Dynamic Data with API Requests
5️⃣ Performance Optimization for Large Datasets
6️⃣ Enhancing User Experience (Keyboard Navigation, Debouncing)
7️⃣ Conclusion
8️⃣ FAQs

1. Understanding Searchable Dropdowns

A searchable dropdown is an input field with a dropdown list that dynamically filters options based on what the user types.

How It Works:

✔ User types in the input field
✔ Dropdown filters the list based on input
✔ Matching results are displayed instantly
✔ Clicking an option selects it

💡 Example Use Cases:
🔹 Country/City selection
🔹 Product search in e-commerce sites
🔹 Auto-suggest fields in forms

Now, let’s build it step by step.

2. HTML & Basic Styling for the Dropdown

We’ll start by creating a basic structure for the dropdown.

HTML Structure:

<div class="dropdown">
    <input type="text" id="searchInput" placeholder="Search..." autocomplete="off">
    <ul id="dropdownList" class="dropdown-list"></ul>
</div>

CSS Styling:

.dropdown {
    position: relative;
    width: 300px;
}

#searchInput {
    width: 100%;
    padding: 8px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

.dropdown-list {
    position: absolute;
    width: 100%;
    max-height: 200px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid #ccc;
    border-radius: 5px;
    display: none;
    list-style: none;
    padding: 0;
}

.dropdown-list li {
    padding: 8px;
    cursor: pointer;
}

.dropdown-list li:hover {
    background: #f0f0f0;
}

This will create a simple dropdown that appears below the input field.

3. Implementing Search Logic with JavaScript

Now, let’s add JavaScript to filter the dropdown list as the user types.

const searchInput = document.getElementById("searchInput");
const dropdownList = document.getElementById("dropdownList");

// Sample dataset
const items = ["Apple", "Banana", "Cherry", "Date", "Grapes", "Mango", "Orange", "Pineapple"];

function filterItems(searchText) {
    // Convert input to lowercase for case-insensitive search
    const filteredItems = items.filter(item => item.toLowerCase().includes(searchText.toLowerCase()));

    // Clear previous results
    dropdownList.innerHTML = "";

    // Show the dropdown only if results exist
    if (filteredItems.length > 0) {
        dropdownList.style.display = "block";
        filteredItems.forEach(item => {
            let li = document.createElement("li");
            li.innerText = item;
            li.onclick = () => selectItem(item);
            dropdownList.appendChild(li);
        });
    } else {
        dropdownList.style.display = "none";
    }
}

function selectItem(value) {
    searchInput.value = value;
    dropdownList.style.display = "none";
}

// Listen for input changes
searchInput.addEventListener("input", () => filterItems(searchInput.value));

Now, the dropdown dynamically filters items as you type!

4. Handling Dynamic Data with API Requests

Instead of using static data, let’s fetch data dynamically from JSONPlaceholder (fake API).

async function fetchData() {
    const response = await fetch("https://jsonplaceholder.typicode.com/users");
    const data = await response.json();
    return data.map(user => user.name); // Extracting names
}

async function initializeDropdown() {
    const users = await fetchData();
    items.push(...users); // Add fetched users to dropdown
}

// Fetch data on page load
initializeDropdown();

Now, our dropdown is powered by live API data!

5. Performance Optimization for Large Datasets

When dealing with thousands of records, filtering in real-time can be slow. Here are some optimizations:

1️⃣ Debounce the Input (Avoid Too Many API Calls)

let debounceTimer;
searchInput.addEventListener("input", () => {
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(() => filterItems(searchInput.value), 300);
});

✅ This reduces unnecessary function calls when users type quickly.

2️⃣ Virtualized Rendering (Show Only Visible Items)

For thousands of options, rendering all at once is inefficient. Instead, we should only render visible items.

Use Intersection Observer API or Libraries like react-window for optimized rendering.

6. Enhancing User Experience

1️⃣ Keyboard Navigation

let currentIndex = -1;
searchInput.addEventListener("keydown", (e) => {
    let options = dropdownList.querySelectorAll("li");

    if (e.key === "ArrowDown") {
        currentIndex = (currentIndex + 1) % options.length;
    } else if (e.key === "ArrowUp") {
        currentIndex = (currentIndex - 1 + options.length) % options.length;
    } else if (e.key === "Enter") {
        selectItem(options[currentIndex].innerText);
    }

    options.forEach(option => option.classList.remove("highlight"));
    if (options[currentIndex]) options[currentIndex].classList.add("highlight");
});

✅ Now, users can navigate with arrow keys!

Complete Code for Searchable Dropdown in JavaScript

This is the full implementation of the searchable dropdown with dynamic data from an API, performance optimizations using debouncing, and keyboard navigation support.

HTML Structure:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Searchable Dropdown with Dynamic Data</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>

<div class="dropdown">
    <input type="text" id="searchInput" placeholder="Search..." autocomplete="off">
    <ul id="dropdownList" class="dropdown-list"></ul>
</div>

<script src="app.js"></script>
</body>
</html>

CSS Styling (styles.css):

.dropdown {
    position: relative;
    width: 300px;
}

#searchInput {
    width: 100%;
    padding: 8px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

.dropdown-list {
    position: absolute;
    width: 100%;
    max-height: 200px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid #ccc;
    border-radius: 5px;
    display: none;
    list-style: none;
    padding: 0;
}

.dropdown-list li {
    padding: 8px;
    cursor: pointer;
}

.dropdown-list li:hover {
    background: #f0f0f0;
}

.highlight {
    background-color: #d3d3d3;
}

JavaScript Code (app.js):

const searchInput = document.getElementById("searchInput");
const dropdownList = document.getElementById("dropdownList");

// Sample dataset
const items = ["Apple", "Banana", "Cherry", "Date", "Grapes", "Mango", "Orange", "Pineapple"];

let debounceTimer;

async function fetchData() {
    const response = await fetch("https://jsonplaceholder.typicode.com/users");
    const data = await response.json();
    return data.map(user => user.name); // Extracting names
}

async function initializeDropdown() {
    const users = await fetchData();
    items.push(...users); // Add fetched users to dropdown
}

function filterItems(searchText) {
    // Convert input to lowercase for case-insensitive search
    const filteredItems = items.filter(item => item.toLowerCase().includes(searchText.toLowerCase()));

    // Clear previous results
    dropdownList.innerHTML = "";

    // Show the dropdown only if results exist
    if (filteredItems.length > 0) {
        dropdownList.style.display = "block";
        filteredItems.forEach(item => {
            let li = document.createElement("li");
            li.innerText = item;
            li.onclick = () => selectItem(item);
            dropdownList.appendChild(li);
        });
    } else {
        dropdownList.style.display = "none";
    }
}

function selectItem(value) {
    searchInput.value = value;
    dropdownList.style.display = "none";
}

// Debounce the input to avoid excessive filtering
searchInput.addEventListener("input", () => {
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(() => filterItems(searchInput.value), 300);
});

// Keyboard navigation logic
let currentIndex = -1;
searchInput.addEventListener("keydown", (e) => {
    let options = dropdownList.querySelectorAll("li");

    if (e.key === "ArrowDown") {
        currentIndex = (currentIndex + 1) % options.length;
    } else if (e.key === "ArrowUp") {
        currentIndex = (currentIndex - 1 + options.length) % options.length;
    } else if (e.key === "Enter") {
        selectItem(options[currentIndex].innerText);
    }

    options.forEach(option => option.classList.remove("highlight"));
    if (options[currentIndex]) options[currentIndex].classList.add("highlight");
});

// Initialize dropdown with API data
initializeDropdown();

// Listen for input changes
searchInput.addEventListener("input", () => filterItems(searchInput.value));

Explanation of the Code:

  1. HTML Structure:
    • A basic input field for user text input.
    • A list (ul) to display the filtered options.
  2. CSS Styling:
    • Basic styling for the dropdown and the input field.
    • Hover effect for list items and a .highlight class for keyboard navigation.
  3. JavaScript:
    • fetchData(): Fetches dynamic data (user names) from the JSONPlaceholder API.
    • initializeDropdown(): Initializes the dropdown with both the static items and the fetched user names.
    • filterItems(): Filters items based on user input and displays matching options in the dropdown.
    • Debouncing: Implements a delay before filtering starts to avoid too many rapid API calls or filtering operations.
    • Keyboard Navigation: Allows the user to navigate the list with ArrowUp, ArrowDown, and Enter keys.

Running the Code:

  • Create three files: index.html, styles.css, and app.js.
  • Copy the code above into their respective files.
  • Open the index.html file in your browser.

Now, you have a fully functional, searchable dropdown component that dynamically filters options based on user input, supports large datasets, and allows for keyboard navigation.

7. Conclusion

🎯 Key Takeaways:
Dynamic filtering for better UX
Optimized for large datasets using debouncing & virtualization
API integration for live data
Keyboard navigation for accessibility

A searchable dropdown is a crucial UI component that enhances user experience. Implement these optimizations, and you’ll have a high-performance, reusable dropdown for any project!

Frequently Asked Questions (FAQs)

1. What is a searchable dropdown in JavaScript?

A searchable dropdown in JavaScript allows users to filter through a list of options dynamically as they type. It helps in creating user-friendly and space-efficient interfaces, especially when dealing with large datasets.

2. How do I implement a searchable dropdown in JavaScript?

To implement a searchable dropdown in JavaScript, you can create an input field for user search, filter through a list of options as the user types, and display the matching results in a dropdown. You can also use debouncing to optimize performance when handling large datasets.

3. Can I create a searchable dropdown with dynamic data from an API?

Yes, you can create a searchable dropdown that fetches data dynamically from an API like JSONPlaceholder or your own data source. The dropdown can filter and display results as users type, offering a seamless experience even with large sets of data.

4. How can I improve the performance of a searchable dropdown for large datasets?

For large datasets, performance can be improved by implementing debouncing, which delays the filtering operation until the user stops typing for a specified time. This prevents excessive function calls and enhances speed. You can also implement lazy loading or pagination to load data progressively.

5. How do I add keyboard navigation to a searchable dropdown?

You can add keyboard navigation by detecting ArrowDown, ArrowUp, and Enter keys to move through and select options. This improves accessibility, allowing users to navigate the dropdown without using a mouse.

6. What is debouncing in a searchable dropdown?

Debouncing is a technique used to limit the rate at which a function is executed. In the case of a searchable dropdown, it waits for the user to stop typing for a predefined time before triggering the search and filtering the options. This helps in reducing the load on the browser and API.

7. How can I style a searchable dropdown in CSS?

To style a searchable dropdown, you can use CSS properties like border-radius, background-color, and hover effects to customize the appearance. Ensure that the dropdown is easy to read and navigate, especially on mobile devices.

8. Can I create a multi-select searchable dropdown?

Yes, you can extend the functionality of a searchable dropdown to allow multi-select options. This can be achieved by adding checkboxes next to each dropdown item and updating the selected values dynamically.

9. How do I make a searchable dropdown accessible?

To make a searchable dropdown accessible, ensure that it supports keyboard navigation, provides proper ARIA roles for screen readers, and is focusable for users with disabilities. Also, consider adding proper descriptive labels for better usability.

10. What are some use cases for a searchable dropdown?

Searchable dropdowns are commonly used in forms, e-commerce websites, content management systems, filters, and search interfaces where users need to select from a large number of options efficiently.

Muhaymin Bin Mehmood

About Muhaymin Bin Mehmood

Front-end Developer skilled in the MERN stack, experienced in web and mobile development. Proficient in React.js, Node.js, and Express.js, with a focus on client interactions, sales support, and high-performance applications.

Join our newsletter

Subscribe now to our newsletter for regular updates.

Copyright © 2025 Mbloging. All rights reserved.