Guides / Building Search UI / UI & UX patterns

Facet display in React InstantSearch

This is the React InstantSearch v7 documentation. React InstantSearch v7 is the latest version of React InstantSearch and the stable version of React InstantSearch Hooks.

If you were using React InstantSearch v6, you can upgrade to v7.

If you were using React InstantSearch Hooks, you can still use the React InstantSearch v7 documentation, but you should check the upgrade guide for necessary changes.

If you want to keep using React InstantSearch v6, you can find the archived documentation.

Learn how to configure, order, hide, and display facets and facet values using the dashboard, API, and your choice of InstantSearch or a custom solution.

Manage facet display from the Algolia dashboard

Control the facets to display and their order by sending a renderingContent parameter with your search query. Your UI must interpret this setting so your users can interact with the index.

The main implementation steps are:

  1. Configure the attributes to use for faceting on your search index.
  2. Configure your facet display.
  3. Build a UI capable of interpreting the renderingContent setting. For this step, use InstantSearch library widgets. You can create a UI with other tools but must write the interpretation logic yourself.

Configure facet display from the dashboard

  1. Select the Search product icon on your dashboard and then select your index.
  2. Click the Configuration tab.
  3. Under the Filtering and Faceting category, click Facet display.
  4. Click Add facet to display to choose the facets you want to display in your UI.
  5. Use the = icon next to each facet to drag them into the correct position. The order you set here determines how facets display in your UI.
  6. For each facet, click the pen icon to configure how the engine should display the facet’s values. You can:

    • Pin some values at the top of the list if you want to display them first.
    • Hide some values from the list entirely.
    • Choose how to display the remaining facet values: by count, alphabetically, or only display pinned values.
  7. To remove a facet from the list and stop displaying it in your UI, click the trash icon.
  8. Save your changes.

If you want to only display the facets “brand”, “size”, and “color” in your UI, declare than as attributes for faceting and add them to the list of facets to display.

With those three facets added, you want to display the brands alphabetically. However:

  • Since you have a specific partnership with the brand “Lacoste”, you want the brand to always display on top.
  • Sizes need to be in a specific order: S, M, L, XL. You may have sizes in different formats in your data, but for the sake of clarity, you only want to display those four. You pin them at the top in the correct order and choose not to display other values
  • For colors, you want to display them by count and not pin any specific value.

As soon as you save the changes, the UI adapts to this new configuration.

This approach lets you configure a static facet display. If you want a more dynamic approach that customizes the display of the facets and values for a specific query or category, see the Merchandising facets.

Configure facet display with the API

To replicate the preceding dashboard example, use the API client’s setSettings method with the following settings applied to your index:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$index->setSettings([
  'renderingContent' => [
    'facetOrdering' => [
      'facets' => [
        'order' => ['brand', 'size', 'color']
      ],
      'values' => [
        'brand'=> [
          'order' => ['Uniqlo'],
          'sortRemainingBy' => 'alpha'
        ],
        'size'=> [
          'order' => ['S', 'M', 'L','XL'],
          'sortRemainingBy' => 'hidden'
        ],
        'color'=> [
          'sortRemainingBy' => 'count'
        ]
      ]
    ]
  ]
]);

Hide facet values

Hiding facet values is not supported in InstantSearch iOS and InstantSearch Android.

The following example shows three facets: author, brand, and on_sale (in that order). The author facet is sorted by number of hits, the brand facet is ordered alphabetically, always shows the facet value “Kensington” in the first position (pinned) and never shows the value “Bosch” (hidden). The on_sale facet only shows the pinned true value.

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
index
  .setSettings({
    renderingContent: {
      facetOrdering: {
        facets: {
          order: ['author', 'brand', 'on_sale'],
        },
        values: {
          "author": {
            "sortRemainingBy": "count"
          },
          "brand": {
            "order": ["Kensington"],
            "hide": ["Bosch"]
            "sortRemainingBy": "alpha"
          },
          "on_sale": {
            "order": ["true"],
            "sortRemainingBy": "hidden"
          },
        },
      },
    },
  })
  .then(() => {
    // done
  });

Build the UI with InstantSearch

The simplest way to control facet display is to use InstantSearch. This UI library has built-in widgets that understand the renderingContent data returned by searches. This data includes everything you need to show facets how you want.

Facet display requirements for InstantSearch

To make your UI compatible with the facet display feature:

  • Add refinement widgets for the different facets.
  • Add a dynamicWidgets container around the widgets you want to sort.
  • In those widgets, remove any custom sortBy or set facetOrdering to true.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// This example assumes you're including InstantSearch.js in your web
// page via a CDN. If you're using it with a package manager, you
// should adjust the way you import InstantSearch.js and its widgets.
const { dynamicWidgets, menu, hierarchicalMenu } = instantsearch.widgets;

search.addWidgets([
  dynamicWidgets({
    container: '#dynamic-widgets',
    fallbackWidget: ({ container, attribute }) =>
      menu({ container, attribute, limit: 10 }),
    widgets: [
      container =>
        hierarchicalMenu({
          limit: 10,
          attributes: [
            'hierarchicalCategories.lvl0',
            'hierarchicalCategories.lvl1',
          ],
        }),
    ],
  }),
])

Upgrade InstantSearch

If you already built your UI using InstantSearch, you may need to update it to use the dynamic widgets introduced in the following versions:

  • InstantSearch.js: available from version 4.22.0
  • Vue InstantSearch: available from version 4.1.0
  • React InstantSearch: available from version 6.14.0
  • InstantSearch iOS: available from version 7.12.0
  • InstantSearch Android: available from version 2.11.0

Check the upgrade guide for InstantSearch to upgrade your UI to the latest version.

Optimize dynamic widget network requests

Algolia automatically mounts the appropriate widgets for the search results.

  • In versions 4.32 to 4.35, dynamic widgets request all facets and generate an extra network request for this. To avoid this, set facets to [] (empty).
  • In version 4.36 and later, to avoid an extra request, facets is set to [*] by default. If you prefer to do two network requests with only the relevant facets returned, set facets to [].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// This example assumes you're including InstantSearch.js in your web
// page via a CDN. If you're using it with a package manager, you
// should adjust the way you import InstantSearch.js and its widgets.
const { dynamicWidgets, menu, hierarchicalMenu } = instantsearch.widgets;

search.addWidgets([
  dynamicWidgets({
    container: '#dynamic-widgets',
    fallbackWidget: ({ container, attribute }) =>
      menu({ container, attribute, limit: 10 }),
    widgets: [
      container =>
        hierarchicalMenu({
          limit: 10,
          attributes: [
            'hierarchicalCategories.lvl0',
            'hierarchicalCategories.lvl1',
          ],
        }),
    ],
    // do two network requests
    facets: []
  }),
])

Widget limitation

Applies to:

  • InstantSearch.js v4.36 and later
  • React InstantSearch v7 and later
  • Vue InstantSearch v4.3 and later

Dynamic widgets can show up to 1,000 facets. If you do have more than that, here’s how to display the ones with the most results.

  1. Add an applicable_facets facet to every object:
1
2
3
4
5
  {
    "applicable_facets": ["special_type", "color"],
    "special_type": "stretch",
    "color": "blue"
  }
  1. Configure the dynamic widget so it doesn’t ask for all facets. Many of them will be hidden anyway because of the 1,000 facet limit. To do this, set facets to [] (empty).
1
2
3
dynamicWidgets({
  facets: []
})
  1. Ensure that applicable_facets is always requested. Such as from a hidden menu:
1
connectMenu(() => {})({ attribute: "applicable_facets" })
  1. Use transformItems of dynamicWidgets to use applicable_facets for dynamic widget rendering:
1
2
3
4
5
6
dynamicWidgets({
  facets: [],
  transformItems(_items, { results }) {
    return Object.keys(results._rawResults[0].facets.applicable_facets);
  }
});

Build the UI without InstantSearch

If you aren’t using InstantSearch to build your UI, you need to build frontend logic to:

  • Interpret the renderingContent parameter returned along search results,
  • Order facets and values based on your interpretation of the renderingContent parameter values.

A custom implementation of frontend search requires:

  • Reading the facet order
  • Reading the facet value order

Read the facet order

If you hardcode the list of facets to display on a page, you can read that from result.renderingContent.facetOrdering.facets.order (all keys are optional). This is the list of attributes that you chose to display and can loop over to display individual facet lists.

Read the facet value order

You need to list the attribute you want to display facets of in searchParameters.facets. Read the possible results from result.facets[facetName]. After fetching those values, you can read the result.renderingContent.facetOrdering.values[facetName] object to sort them. This object has the following keys:

  • order: an array of facet values to pin at the start of the list
  • hide: an array of facet values to hide from the list
  • sortRemainingBy: a string that describes how to sort the remaining values. Either “alpha” (alphabetically, ascending), “count” (value retrieved from facets[facetName][facetValue], descending), or “hidden”, which only displays the ordered items.
Did you find this page helpful?