Form

Fetch typeahead input

Published on

Description anchor

A fetch typeahead input suggests results from a remote endpoint as the user types. It is suited to large or dynamic datasets that cannot be pre-rendered, such as searching a database of records. Each keystroke is debounced and in-flight requests are cancelled, so only the most recent query is shown.

When the confirmed suggestion carries an href, the browser navigates to it — useful for search and navigation. Otherwise the input value is set to the suggestion label, for use inside a form.

Example anchor

Open in new tab(opens in new tab)
View HTML markup
  <form method="POST" novalidate="">
  <div><label for="country">
      <hgroup>
        <h1>Country</h1>
      </hgroup>
    </label> <span id="country-hint">Start typing to search countries</span> <input value="" id="country" name="country" autocapitalize="off" autocorrect="off" spellcheck="false" is="ds-fetch-typeahead" list="country-datalist" data-src="/api/fetch-typeahead.json" aria-describedby="country-hint" /> <datalist id="country-datalist">
      <option value="Australia"></option>
      <option value="Brazil"></option>
      <option value="Canada"></option>
      <option value="France"></option>
      <option value="Germany"></option>
      <option value="India"></option>
      <option value="Japan"></option>
      <option value="Mexico"></option>
      <option value="United Kingdom"></option>
      <option value="United States"></option>
    </datalist></div> <button type="button">Submit</button>
  <p>Need help? <a href="/form/input-fetch-typeahead" target="_top">View our guidance</a></p>
</form>

Fetch contract anchor

Suggestions are requested from the endpoint named by src. The current query is appended as a parameter named by param (defaults to q). Any entries in the criteria object are appended as additional data-criteria-* query parameters, letting you scope results by other filters.

  • src — endpoint base URL, rendered as data-src.
  • param — query parameter name for the typed text, rendered as data-param (default q).
  • criteria — an object of extra filters, each rendered as data-criteria-<key> and sent as a query parameter.

The request is sent with an Accept: application/json header and same-origin credentials. The endpoint must respond with a JSON array of items. Each item needs a label (shown in the menu and used as the input value); value and href are optional, and any additional fields are ignored. When an item has an href, confirming it navigates the browser there instead of filling the field.

  [
  { "value": "CA", "label": "Canada" },
  { "value": "US", "label": "United States", "href": "/countries/us" }
]

Progressive enhancement anchor

The component wraps a plain input associated with a local <datalist>. Without JavaScript, the native datalist provides basic matching against the options you render as children.

With JavaScript, those same datalist options become the offline fallback: if a fetch request fails, the menu is populated from the local options filtered case-insensitively against the query, and the error message is announced. This keeps the field usable even when the endpoint is unreachable.

  • No JavaScript — native <datalist> matching on the rendered options.
  • JavaScript, endpoint reachable — remote suggestions, debounced by 250 ms with stale requests cancelled through an AbortController.
  • JavaScript, fetch failure — the local datalist options are filtered as a fallback.

Internationalization anchor

The status messages shown in the suggestions menu are overridable so they can be translated.

  • textLoading — shown while a request is in flight, rendered as data-i18n-loading.
  • textError — shown when a request fails, rendered as data-i18n-error.
  • textNoResults — shown when the response is empty, rendered as data-i18n-no-results.

Accessibility anchor

  • The enhanced input exposes an ARIA combobox(opens in new tab) with a listbox of options and a live-region status announcing result counts.
  • The label association is preserved: the enhanced input keeps the original id, so the existing <label for="id"> still applies.
  • Suggestions confirm on selection, not on blur, so leaving the field never silently changes the entered value.

Variables anchor

None for input