How to Create an Autocomplete Multi-Select Component with Next.js and NextUI

How to Create an Autocomplete Multi-Select Component with Next.js and NextUI

Creating an Intuitive Multi-Select Autocomplete Component with Next.js and NextUI

In modern web development, building intuitive and user-friendly UI components is crucial. One such component is an autocomplete multi-select dropdown, which allows users to select multiple options from a list. In this blog post, we will walk through how to build an autocomplete multi-select component using Next.js and NextUI. We’ll explore handling user input, filtering options, and managing selected items.

Prerequisites

Before we start, ensure you have the following setup:

  1. Next.js Project: You should have a Next.js project initialized. If not, you can create one using the following command:

     npx create-next-app my-nextjs-app
     cd my-nextjs-app
    
  2. NextUI Library: Install NextUI, which provides components like Input and Chip that we'll use in our project. Install it with:

     npm install @nextui-org/react
    

Component Overview

We will build an AutocompleteMultiple component that allows users to search and select multiple options from a dropdown list. The component will include:

  • Input Field: For user search input.

  • Dropdown List: Shows filtered options based on user input.

  • Selected Options Display: Shows selected items as chips.

Here is the step-by-step implementation of the component.

1. Setup the Component

First, create a new file for your component, e.g., AutocompleteMultiple.tsx. Import necessary modules and define the Option interface.

import { useState, ChangeEvent } from "react";
import { Input, Chip } from "@nextui-org/react";

interface Option {
  label: string;
  value: string;
}

const options: Option[] = [
  { label: "Apple", value: "apple" },
  { label: "Banana", value: "banana" },
  { label: "Orange", value: "orange" },
  { label: "Pineapple", value: "pineapple" },
  { label: "Strawberry", value: "strawberry" }
];

export default function AutocompleteMultiple() {
  const [selectedOptions, setSelectedOptions] = useState<Option[]>([]);
  const [inputValue, setInputValue] = useState<string>("");

2. Handle User Interaction

Define functions to handle selecting, removing, and input changes.

  const handleSelect = (option: Option) => {
    if (!selectedOptions.some((o) => o.value === option.value)) {
      setSelectedOptions([...selectedOptions, option]);
    }
    setInputValue(""); // Clear input after selection
  };

  const handleRemove = (option: Option) => {
    setSelectedOptions(selectedOptions.filter((o) => o.value !== option.value));
  };

  const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
    setInputValue(event.target.value); // Extract value from event
  };

3. Filter Options

Filter the available options based on user input and ensure selected options are excluded from the dropdown list.

  const filteredOptions = options.filter(
    (option) =>
      option.label.toLowerCase().includes(inputValue.toLowerCase()) &&
      !selectedOptions.some((o) => o.value === option.value)
  );

4. Render the Component

Render the input field, dropdown list, and selected options display.

  return (
    <div>
      <Input
        name="q_list"
        placeholder="Type to search and select..."
        value={inputValue}
        onChange={handleInputChange} // Corrected this line
      />

      {/* Custom Dropdown List for Autocomplete */}
      {inputValue && (
        <div>
          {filteredOptions.map((option) => (
            <div
              key={option.value}
              style={{
                padding: "8px",
                cursor: "pointer",
                backgroundColor: "#f0f0f0",
                marginTop: "4px"
              }}
              onClick={() => handleSelect(option)}
            >
              {option.label}
            </div>
          ))}
        </div>
      )}

      <div style={{ marginTop: "10px" }}>
        {selectedOptions.map((option) => (
          <Chip
            key={option.value}
            onClose={() => handleRemove(option)} // Remove item from list
            color="primary"
            variant="flat"
            size="sm"
            style={{ margin: "0 5px 5px 0" }}
          >
            {option.label}
          </Chip>
        ))}
      </div>
    </div>
  );
}

Conclusion
The AutocompleteMultiple component we built demonstrates a practical approach to handling user input and selections in a multi-select autocomplete dropdown. By leveraging React hooks and NextUI components, we created a robust and user-friendly interface. With enhancements and customizations, you can adapt this component to fit various use cases and improve user experience in your applications.