v1.6.x-dev NDS IQ v6

Autocomplete - National Design System

Remote typeahead search input with keyboard navigation, result highlighting, and debounced API fetching

Autocomplete Input

Type-ahead search with remote data fetching and dropdown results

<div class="nds-form-container" data-url="/api/services" data-name="Title"> <div class="nds-form-header"> <label for="autocomplete-1"> <span class="nds-label">Search services</span> </label> </div> <div class="nds-form-control"> <i class="nds-icon nds-hgi-search-01" aria-hidden="true"></i> <input type="text" id="autocomplete-1" autocomplete="on" placeholder="Type to search..."> <div class="nds-form-action"> <button class="nds-btn nds-subtle nds-clear" type="button" aria-label="Clear input" hidden> <i class="nds-icon nds-hgi-cancel-01" aria-hidden="true"></i> </button> </div> </div> <div class="nds-form-footer" data-feedback-target hidden></div> </div>

Built-in Features

What you get out of the box with zero configuration

Auto-initialization

Initializes automatically on any input with autocomplete="on" inside a container with data-url. For dynamic content, call NDS.Autocomplete.reinit(). The instance itself is built on the field's first focus, which covers every path a user takes but not a field that JS drives before anyone touches it: to write a value and fetch against a field that has never been focused, construct it first with NDS.Autocomplete.create(container).

Result Highlighting

Matching characters in results are highlighted with <mark> tags. Results display in a dropdown built on the NDS Dropmenu component.

Keyboard Navigation

Arrow keys navigate results, Enter selects the active item, Escape closes the dropdown, Tab closes without selecting, Home jumps to the first item, End jumps to the last item. The active item scrolls into view automatically.

Debounced Fetching

API requests are debounced at 300ms. Previous in-flight requests are cancelled via AbortController. Loading state shows on the input during fetch.

Bilingual Support

Works with Arabic and English content. Empty state message adapts to the page language. RTL and LTR layouts supported.

Form Integration

Selected values sync to the input. Clear button resets the selection. Works with the forms validation and status API.

Search Box Auto-submit

When the container also has class nds-search-box, selecting a result automatically clicks the nearest .nds-search-btn to submit the search without extra interaction.

Usage Guidelines

When and how to use autocomplete inputs effectively

When to Use

  • Search fields that query a remote API for suggestions as the user types
  • Large datasets where showing all options in a select dropdown is impractical
  • Service search, city lookup, product search, or any entity search
  • Set data-min-chars to control when fetching begins (default: 3 characters)
  • For static option lists, use a select dropdown instead

JavaScript API

// Auto-initializes on .nds-form-container[data-url] with autocomplete="on" // For dynamic content: NDS.Autocomplete.reinit(); // Create an instance programmatically (options are optional) var instance = NDS.Autocomplete.create(containerElement, { // Override client-side filtering (used in both fetch modes) filter: function(items, query) { return items.filter(/* … */); }, // Override per-row label rendering; developer owns escaping renderItem: function(item, query) { return '<strong>' + item.Title + '</strong>'; } }); // Destroy an instance instance.destroy(); // Listen for selection container.addEventListener('nds:autocomplete:select', function(e) { console.log('Selected item object:', e.detail.item); console.log('Display text:', e.detail.text); }); // Listen for results fetched container.addEventListener('nds:autocomplete:fetch', function(e) { console.log('Query:', e.detail.query); console.log('Results:', e.detail.results); }); // Listen for clear container.addEventListener('nds:autocomplete:clear', function(e) { console.log('Input cleared'); });

Configuration Attributes

  • data-url on the container: API endpoint that returns JSON
  • data-name: JSON field name to display in results (default: "Title")
  • data-min-chars: minimum characters before fetching starts (default: 3)
  • data-query-param: query string parameter name sent to the API (default: "q")
  • data-results-path: dot notation path to the results array in the response (e.g. "response.items"). Without it, the component auto-detects flat arrays or objects with results or data keys
  • data-fetch: fetch mode, either "each" (default) or "once". With "each" the API is called on every keystroke and the server filters results. With "once" the full list is fetched once on first input, cached, and filtered client-side on each keystroke. Use "once" for small static datasets such as countries, currencies, or departments.
  • data-empty-message: custom text for the "no results" placeholder shown when a query matches nothing (default: localized "No results")
  • data-empty-icon: icon classes for the "no results" placeholder (default: nds-icon nds-hgi-search-01)

API Response Format

With the default data-fetch="each" mode, the component sends a GET request per keystroke (e.g. /api/services?q=term) and the server handles filtering. With data-fetch="once", the full URL is fetched once with no query parameter and filtering is done client-side. Both modes expect JSON in one of these formats:

// Flat array [{ "Title": "Item one" }, { "Title": "Item two" }] // Object with "results" or "data" key { "results": [{ "Title": "Item one" }] } { "data": [{ "Title": "Item one" }] } // The display field matches data-name (default: "Title") // Extra fields are passed through in event detail on selection [{ "Id": 1, "Title": "Request a service", "Category": "Services" }] // Nested response: use data-results-path="response.items" { "response": { "items": [{ "Title": "Item one" }], "total": 42 } } // The component renders up to 20 results // Filtering: server-side with data-fetch="each" (default), client-side with data-fetch="once"
Last Modified Date: 04/08/2026 - 04:02 PM
Was this page useful?
60% of users said Yes from 2843 Feedbacks