npm.io
5.0.0 • Published yesterday

@preline/combobox

Licence
Licensed under MIT and Preline UI Fair Use License
Version
5.0.0
Deps
0
Size
196 kB
Vulns
0
Weekly
0
Stars
6.4K

ComboBox

Dynamic suggestions as users type in an input field.

npm License: MIT Demo

Contents

Overview

The ComboBox component provides an autocomplete input field with dynamic suggestions. It supports both client-side filtering and API-based data fetching, customizable templates, and flexible data rendering options.

Key Features:

  • Dynamic autocomplete suggestions
  • Client-side and API-based data fetching
  • Customizable item templates
  • Keyboard navigation support
  • Programmatic control via JavaScript API
  • Event system for selection tracking
  • Accessibility attributes (ARIA) built-in

Installation

To get started, install ComboBox plugin via npm, else you can skip this step if you are already using Preline UI as a package.

npm i @preline/combobox
CSS

Use @source to register the plugin's JavaScript path for Tailwind CSS scanning, then @import the plugin's CSS files into your Tailwind CSS file.

@import "tailwindcss";

/* @preline/combobox */
@source "../node_modules/@preline/combobox/*.js";
@import "./node_modules/@preline/combobox/variants.css";
@import "./node_modules/@preline/combobox/theme.css";
JavaScript

Include the JavaScript that powers the interactive elements near the end of your </body> tag:

<script src="./node_modules/@preline/combobox/index.js"></script>
Manual Initialization

Use the non-auto entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly.

<script type="module">
  import HSCombobox from "@preline/combobox/non-auto.mjs";

  new HSCombobox(document.querySelector("#combobox"));
</script>
Via Bundler

When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module.

@preline/combobox is the auto-init entry: it scans the DOM and initializes matching elements automatically.

import "@preline/combobox";

@preline/combobox/non-auto is the manual entry: use it when you want explicit control over when initialization happens, either via autoInit() or by creating a specific instance yourself.

import HSCombobox from "@preline/combobox/non-auto";

HSCombobox.autoInit();

// Or initialize a specific element manually
const el = document.querySelector("#combobox");
if (el) new HSCombobox(el);
TypeScript

This package ships with TypeScript type definitions. No additional @types/ package is needed.

Basic usage

The following example demonstrates the minimal HTML structure required for a combobox component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The combobox shows suggestions as the user types.

<div class="inline-flex relative" data-hs-combo-box>
  <div class="relative">
    <input type="text" role="combobox" aria-expanded="false" value="" data-hs-combo-box-input />
  </div>
  
  <div class="absolute z-50" style="display: none;" data-hs-combo-box-output>
    <div class="cursor-pointer" tabindex="0" data-hs-combo-box-output-item>
      <span data-hs-combo-box-search-text="1" data-hs-combo-box-value>1</span>
    </div>
    <div class="cursor-pointer" tabindex="1" data-hs-combo-box-output-item>
      <span data-hs-combo-box-search-text="2" data-hs-combo-box-value>2</span>
    </div>
  </div>
</div>

Structure Requirements:

  • data-hs-combo-box: Required on the container element
  • data-hs-combo-box-input: Required on the input element
  • data-hs-combo-box-output: Required on the dropdown container
  • data-hs-combo-box-output-item: Required on each suggestion item
  • data-hs-combo-box-search-text: Required on the searchable text element within each item
  • Proper ARIA attributes (role="combobox", aria-expanded)

Initial State:

  • Set aria-expanded="false" on the input initially
  • Add style="display: none;" to the output container initially
  • Output visibility is controlled by the plugin

Configuration Options

Data Options

Data options are specified in the data-hs-combo-box attribute and various data attributes.

Attribute Target Element Type Default Description
data-hs-combo-box Container - - Activate a ComboBox by specifying on an element. Should be added to the container.
:gap Inside data-hs-combo-box number 5 Determines the indent from the input field to the dropdown list in pixels.
:viewport Inside data-hs-combo-box string | HTMLElement null Determines which element will be the parent when calculating the position of the dropdown list. By default it is calculated relative to the document.
:minSearchLength Inside data-hs-combo-box number 0 Specifies the minimum number of characters that must be entered before the search function becomes active.
:apiUrl Inside data-hs-combo-box string | null null Specifies the API address for fetching suggestions.
:apiDataPart Inside data-hs-combo-box string | null null Determines which part of the returned data will be taken as the main data array. If this parameter is empty, then the root is taken as a basis.
:apiQuery Inside data-hs-combo-box string | null null Defines request parameters, such as limit.
:apiSearchQuery Inside data-hs-combo-box string | null null Defines the name of the search parameter.
:apiHeaders Inside data-hs-combo-box string | null null Defines request headers.
:apiSearchPath Inside data-hs-combo-box string | null null A string that specifies the endpoint path for the API request, excluding the base URL. Note: apiSearchPath and apiSearchDefaultPath are mutually exclusive with apiSearchQuery.
:apiSearchDefaultPath Inside data-hs-combo-box string | null null A string that defines the default API endpoint path to be used when the input field is empty. Note: apiSearchPath and apiSearchDefaultPath are mutually exclusive with apiSearchQuery.
:outputItemTemplate Inside data-hs-combo-box string | null Default template Defines a template for a single item in a dropdown list.
:outputEmptyTemplate Inside data-hs-combo-box string | null Default template Defines a template for an empty placeholder.
:outputLoaderTemplate Inside data-hs-combo-box string | null Default template Defines a template for the loader when loading data.
:preventAutoPosition Inside data-hs-combo-box boolean false If true, it disables dropdown auto-positioning.
:preventClientFiltering Inside data-hs-combo-box boolean true (if :apiSearchQuery is not empty) If true, it disables client-side filtering.
:keepOriginalOrder Inside data-hs-combo-box boolean false If true, it keeps the original order of items.
:preserveSelectionOnEmpty Inside data-hs-combo-box boolean true If true, it preserves the selected value when the input is empty.
data-hs-combo-box-input Input element - - Determines which element (input) inside the initialized container will be responsible for entering data.
data-hs-combo-box-output Output container - - Determines which element inside the initialized container will be responsible for data output.
data-hs-combo-box-toggle Toggle element - - Defines an element inside the initialized container that will be responsible for hiding/showing the dropdown list.
data-hs-combo-box-close Close element - - Defines an element inside the initialized container that will be responsible for hiding the dropdown list.
data-hs-combo-box-open Open element - - Defines an element inside the initialized container that will be responsible for showing the dropdown list.
data-hs-combo-box-output-item Item element - - Defines an element inside the initialized container that will be responsible for displaying each individual data element.
data-hs-combo-box-search-text Search text element - - Defines the element within which text will be searched.
data-hs-combo-box-value Value element - - Defines an element whose text will be set as a value when selected.
data-hs-combo-box-output-item-field Item field string | string[] - Defines a data field that will be taken to fill the element with text.
data-hs-combo-box-output-item-attr Item attribute - - Defines the attributes that will be filled with the corresponding data. For example, the src attribute of an image.
:valueFrom Inside data-hs-combo-box-output-item-attr string - Defines the name of the field from which data will be taken.
:attr Inside data-hs-combo-box-output-item-attr string - Defines the name of the attribute where the data will be supplied.
Tailwind Modifiers
Name Description
hs-combo-box-active:* A modifier that allows you to set Tailwind classes when ComboBox has been opened.
hs-combo-box-has-value:* A modifier that allows you to set Tailwind classes when ComboBox's input has value.
hs-combo-box-selected:* A modifier that allows you to set Tailwind classes when data-hs-combo-box-output-item has been selected.
hs-combo-box-tab-active:* A modifier that allows you to set Tailwind classes to the active group item (tab) when groupingType is tabs.

JavaScript API

The HSComboBox object is available in the global window object after the plugin is loaded.

Instance Methods

These methods are called on a combobox instance.

Method Parameters Return Type Description
getCurrentData() None object | object[] Returns the data of the selected element as an object. This data must first be assigned as a value to the data parameter data-hs-combo-box-item-stored-data when standard rendering. When rendering via the API, the data is automatically substituted into the data attribute.
setCurrent() None void Sets the current selection based on the input value.
open(val) val: string (optional) boolean Opens the autosuggestion list. Optionally accepts a value to set in the input. Returns true if opened successfully, false otherwise.
close(val, data) val: string | null (optional)
data: object | null (optional)
boolean Closes the autosuggestion list. Optionally accepts a value and data to set. Returns true if closed successfully, false otherwise.
recalculateDirection() None void Forces recalculation of autosuggestion list positions. Useful after window resize or layout changes.
destroy() None void Destroys the combobox instance, removes all generated markup, classes, and event listeners. Use when removing combobox from DOM.
Static Methods

These methods are called directly on the HSComboBox class.

Method Parameters Return Type Description
HSComboBox.getInstance(target, isInstance) target: HTMLElement | string (CSS selector)
isInstance: boolean (optional)
HSComboBox | { id: string | number, element: HSComboBox } | null Returns the combobox instance associated with the target. If isInstance is true, returns collection item object { id, element } where element is the HSComboBox instance. If isInstance is false or omitted, returns the HSComboBox instance directly. Returns null if combobox instance is not found.
HSComboBox.autoInit() None void Reinitializes all ComboBoxes on the page. Useful after dynamically adding comboboxes to DOM.
HSComboBox.close(target) target: HTMLElement | string (CSS selector) void Closes the combobox identified by target. Accepts a DOM element or CSS selector string.
HSComboBox.closeCurrentlyOpened() None void Closes an already open ComboBox. Useful for closing any open combobox before opening a new one.
Usage Examples

Example 1: Using instance methods (public API)

// Create a new combobox instance
const comboBox = new HSComboBox(document.querySelector('#hs-combo-box'));
const openBtn = document.querySelector('#hs-open-btn');

// Open combobox programmatically
openBtn.addEventListener('click', () => {
  comboBox.open();
});

Example 2: Getting instance and using methods (recommended pattern)

// Get the combobox instance
const instance = HSComboBox.getInstance('#hs-combo-box', true);

if (instance) {
  const { element } = instance; // element is the HSComboBox instance
  const openBtn = document.querySelector('#hs-open-btn');

  // Use instance methods
  openBtn.addEventListener('click', () => {
    element.open();
  });

  // Get selected data
  const selectedData = element.getCurrentData();
  console.log('Selected:', selectedData);

  // Clean up when removing from DOM
  function removeComboBox() {
    element.destroy();
  }
}

Example 3: Destroying combobox instance

const instance = HSComboBox.getInstance('#hs-combo-box', true);

if (instance) {
  const { element } = instance;
  const removeBtn = document.querySelector('#hs-remove-btn');

  removeBtn.addEventListener('click', () => {
    // Clean up before removing from DOM
    element.destroy();
    // Now safe to remove the element
    document.querySelector('#hs-combo-box').remove();
  });
}

Events

Combobox instances emit events that can be listened to for selection lifecycle hooks.

Event Name When Fired Callback Parameter Description
on:select When an item is selected from the dropdown object (the selected item data object) Fires after the user clicks an option in the combobox dropdown.
Event Usage Example
// Get combobox instance
const instance = HSCombobox.getInstance('#hs-combobox', true);

if (instance) {
  const { element } = instance;

  // Listen for item selection
  element.on('select', (data) => {
    console.log('Selected item:', data);
    // Use selected data to update other parts of the UI
  });
}

Common Patterns

Pattern 1: API-based ComboBox

Fetch suggestions from an API endpoint.

<div data-hs-combo-box='{
  "apiUrl": "https://api.example.com/search",
  "apiSearchQuery": "q",
  "minSearchLength": 2
}'>
  <input data-hs-combo-box-input />
  <div data-hs-combo-box-output></div>
</div>
Pattern 2: Programmatic Control

Control combobox from external buttons.

<div id="hs-combo-box-first" data-hs-combo-box>
  <input data-hs-combo-box-input />
  <div data-hs-combo-box-output></div>
</div>

<button id="hs-open-combo-box">Open</button>
<button id="hs-close-combo-box">Close</button>

<script>
  const instance = HSComboBox.getInstance('#hs-combo-box-first', true);
  
  if (instance) {
    const { element } = instance;

    document.querySelector('#hs-open-combo-box').addEventListener('click', () => {
      element.open();
    });

    document.querySelector('#hs-close-combo-box').addEventListener('click', () => {
      element.close();
    });
  }
</script>

License

Copyright (c) 2024 Htmlstream.

Licensed under the MIT License.

Keywords