UI libraries / Autocomplete / Core concepts

Populating autocomplete with sources

The most important aspect of an autocomplete experience is the items you display. They’re usually search results for a query but there are other ways to use them.

Static sources

The most straightforward way to provide items is to return static sources. Each source returns a collection of items.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
autocomplete({
  // ...
  getSources() {
    return [
      {
        sourceId: 'links',
        getItems() {
          return [
            { label: 'Twitter', url: 'https://twitter.com' },
            { label: 'GitHub', url: 'https://github.com' },
          ];
        },
        getItemUrl({ item }) {
          return item.url;
        },
        // ...
      },
    ];
  },
});

Whatever the autocomplete state, it always returns these two items.

Search in static sources

Access the autocomplete state in your sources to search within static sources and update them as users type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
autocomplete({
  // ...
  getSources() {
    return [
      {
        sourceId: 'links',
        getItems({ query }) {
          return [
            { label: 'Twitter', url: 'https://twitter.com' },
            { label: 'GitHub', url: 'https://github.com' },
          ].filter(({ label }) =>
            label.toLowerCase().includes(query.toLowerCase())
          );
        },
        getItemUrl({ item }) {
          return item.url;
        },
        // ...
      },
    ];
  },
});

Before moving on to more complex sources, here’s a closer look at the code.

The getSources function returns an array of sources. Each source implements a getItems function to return the items to display. These items can be a simple static array, but you can also use a function to refine items based on the query. The getItems function is called whenever the input changes.

By default, autocomplete items are meant to be hyperlinks. To decide which pager to visit, create a getItemURL function. It enables the keyboard accessibility feature, allowing users to open items in the current tab, a new tab, or a new window from their keyboard.

Customize items with templates

In addition to defining data sources for items, a source lets you customize how to display items with templates.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
autocomplete({
  // ...
  getSources({ query }) {
    return [
      {
        // ...
        templates: {
          item({ item }) {
            return `Result: ${item.name}`;
          },
        },
      },
    ];
  },
});

Display header and footer elements around the list of items:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
autocomplete({
  // ...
  getSources({ query }) {
    return [
      {
        // ...
        templates: {
          header() {
            return 'Suggestions';
          },
          item({ item }) {
            return `Result: ${item.name}`;
          },
          footer() {
            return 'Footer';
          },
        },
      },
    ];
  },
});

Templates aren’t limited to strings. You can provide any valid virtual DOM element.

Dynamic sources

Static sources can be useful, especially when users haven’t typed anything. However, you might want more robust search capabilities beyond exact matches in strings.

In this case, you could search into one or more Algolia indices using the built-in getAlgoliaResults function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { liteClient as algoliasearch } from 'algoliasearch/lite';
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js';

const searchClient = algoliasearch(
  'latency',
  '6be0576ff61c053d5f9a3225e2a90f76'
);

autocomplete({
  // ...
  getSources() {
    return [
      {
        sourceId: 'products',
        getItems({ query }) {
          return getAlgoliaResults({
            searchClient,
            queries: [
              {
                indexName: 'instant_search',
                query,
              },
            ],
          });
        },
        getItemUrl({ item }) {
          return item.url;
        },
        // ...
      },
    ];
  },
});

Asynchronous sources

The getSources function supports promises to fetch sources from any asynchronous API: Algolia or any third-party API you can query with an HTTP request.

For example, you could use Google Places Query Autocomplete to search for locations and retrieve popular queries that match points of interest.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
autocomplete({
  // ...
  getSources({ query }) {
    return fetch(
      `https://maps.googleapis.com/maps/api/place/queryautocomplete/json?input=${query}&key=YOUR_GOOGLE_PLACES_API_KEY`
    )
      .then((response) => response.json())
      .then(({ predictions }) => {
        return [
          {
            sourceId: 'predictions',
            getItems() {
              return predictions;
            },
            getItemInputValue({ item }) {
              return item.description;
            },
            // ...
          },
        ];
      });
  },
});

The getItemInputValue function returns the value of the item. It lets you fill the search box with a new value whenever users select an item, allowing them to refine their query and retrieve more relevant results.

Multiple sources

You don’t have to return just one set of results. Autocomplete lets you fetch data from several sources and show different kinds of results that are used for different things.

For example, you may want to display Algolia search results and Query Suggestions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import { liteClient as algoliasearch } from 'algoliasearch/lite';
import { autocomplete, getAlgoliaResults } from '@algolia/autocomplete-js';

const searchClient = algoliasearch(
  'latency',
  '6be0576ff61c053d5f9a3225e2a90f76'
);

autocomplete({
  // ...
  getSources({ query }) {
    return [
      {
        sourceId: 'querySuggestions',
        getItems() {
          return getAlgoliaResults({
            searchClient,
            queries: [
              {
                indexName: 'instant_search_demo_query_suggestions',
                query,
              },
            ],
          });
        },
        getItemInputValue() {
          return item.query;
        },
        // ...
      },
      {
        sourceId: 'products',
        getItems() {
          return getAlgoliaResults({
            searchClient,
            queries: [
              {
                indexName: 'instant_search',
                query,
              },
            ],
          });
        },
        getItemUrl({ item }) {
          return item.url;
        },
        // ...
      },
    ];
  },
});

Use the autocomplete-plugin-query-suggestions plugin to retrieve Query Suggestions.

For more information, see Including multiple result types.

Reference

getSources
type: (params: { query: string, state: AutocompleteState, ...setters: Autocomplete Setters }) => Array<AutocompleteSource> | Promise<Array<AutocompleteSource>>

The function to fetch sources and their behaviors.

See source for what to return.

source ➔ source

sourceId
type: string

Unique identifier for the source. It’s used as value for the data-autocomplete-source-id attribute of the source section container.

getItems
type: (params: { query: string, state: AutocompleteState, ...setters }) => Item[] | Promise<Item[]>
Required

The function called when the input changes. You can use this function to filter the items based on the query.

1
2
3
4
5
6
7
8
const items = [{ value: 'Apple' }, { value: 'Banana' }];

const source = {
  getItems({ query }) {
    return items.filter((item) => item.value.includes(query));
  },
  // ...
};
getItemInputValue
type: (params: { item, state: AutocompleteState }) => string` | defaults to `({ state }) => state.query

The function called to get the value of an item. The value is used to fill the search box.

1
2
3
4
5
6
7
8
const items = [{ value: 'Apple' }, { value: 'Banana' }];

const source = {
  getItemInputValue({ item }) {
    return item.value;
  },
  // ...
};
getItemUrl
type: (params: { item: Item, state: AutocompleteState }) => string | undefined

The function called to get the URL of the item. The value is used to add keyboard accessibility features to let users open items in the current tab, a new tab, or a new window.

1
2
3
4
5
6
7
8
9
10
11
const items = [
  { value: 'Google', url: 'https://google.com' },
  { value: 'Amazon', url: 'https://amazon.com' },
];

const source = {
  getItemUrl({ item }) {
    return item.url;
  },
  // ...
};
onSelect
type: (params: { state: AutocompleteState, ...setters, event: Event, item: TItem, itemInputValue: string, itemUrl: string, source: AutocompleteSource }) => void` | defaults to `({ setIsOpen }) => setIsOpen(false)

The function called whenever an item is selected.

onActive
type: (params: { state: AutocompleteState, ...setters, event: Event, item: TItem, itemInputValue: string, itemUrl: string, source: AutocompleteSource }) => void

The function called whenever an item is active.

You can trigger different behaviors if the item is active depending on the triggering event using the event parameter.

templates
type: AutocompleteTemplates

A set of templates to customize how sections and their items are displayed.

See Displaying items with Templates for more information.

Did you find this page helpful?