Concepts / Building Search UI / Conditional display
Oct. 11, 2019

Conditional Display

Handling no results

When a query returns no results, it is important to let the user know that their query led to no results.

By doing so, the UI acknowledges that not all queries lead to some result and with some additional hints you can let them continue to use the search. This way, there is less chance that the user will leave the website to do a search on an external search engine.

There are various strategies that can be implemented for the no-result. This guide will walk you through one that can be easily implemented with InstantSearch.js:

  • first you will improve the message that you provide to the user
  • then you will add a button to let the user clear the filters

Display a message

By default, InstantSearch.js will only display “no results” when there are no results. The bare minimum to handle the no-result case is to provide the user with a message that indicates that no results were found in a friendly fashion.

In order to do that, you can use the InstantSeach.js’ Hits widget option templates.empty:

1
2
3
4
5
6
7
8
9
10
const search = instantsearch(/* parameters */);
search.addWidgets([
  instantsearch.widgets.hits({
    container: 'hits',
    templates: {
      empty: '<p class="info">No results were found with your current filters. Try to remove some filters or change the search query.</p>',
      item: yourItemTemplate
    },
  })
]);

When there are no results, the user will see a paragraph that says: “No results were found with your current filters. Try to remove some filters or change the search query.”.

Let the user clear all the filters

To go further, you can also let the user clear the filters and start their search from scratch. This way, you allow the user to make mistakes.

For this purpose we provide a specific widget clearRefinements. However using it inside the empty template is not possible. Therefore in this particular case, we will rather instead use the routing.

To be able to do this part, you need to have the URL sync mechanism activated so that you can easily clear the filters using the URL. You can activate the URL Sync by adding to your InstantSearch instance:

1
2
3
4
const search = instantsearch({
  /* your other parameters */
  routing: true
});

This gives you a basic configuration of the routing. Check out the complete guide about routing if you want to learn more.

The routing makes your InstantSearch.js app aware of changes in the URL. With this, you can easily influence the parameters of the search. In this case, you want to clear all the filters so you can make a link to this page, without the parameters.

You can do this by customizing again the no-result template and adding it a clear all link:

1
2
3
4
5
6
7
8
9
10
const search = instantsearch(/* parameters */);
search.addWidgets([
  instantsearch.widgets.hits({
    container: 'hits',
    templates: {
      empty: '<p class="info">No results were found with your current filters. <br/> <a class="button" href=".">Clear all the filters</a></p>',
      item: yourItemTemplate
    },
  })
]);

The secret of this last part is to use . as the href of the “clear all the filters” link. You can go further and make this link look like a button.

Handling empty queries

By default, InstantSearch.js displays search results even when the query is empty. You may find cases where you want to hide results on empty queries. There are multiple ways of achieving that behavior.

Using the helper state

This is hiding the results container if the query is empty.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const search = instantsearch({
  /* other parameters */
  searchFunction(helper) {
    const container = document.querySelector('#results');

    if (helper.state.query === '') {
      container.style.display = 'none';
    } else {
      container.style.display = '';
    }

    helper.search();
  }
});

Using a connector

This is using the connectHits connector.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const search = instantsearch(/* parameters */);
const customHits = instantsearch.connectors.connectHits(
  (renderOptions, isFirstRender) => {
    const { results, widgetParams} = renderOptions
    const { container } = widgetParams;

    container.innerHTML = results && results.query ? `
      <div>
        Searching for query: "${results.query}".
      </div>
    ` : `
      <div>
        No query.
      </div>
    `
  }
);

search.addWidgets([
  customHits({
    container: document.querySelector('#hits'),
  })
]);

Handling errors

Even with the best intentions errors can happen when querying with Algolia. This guide will help you make your search UI react to such issues.

Making an error-handling widget

In this part, you will create a custom widget to handle errors that can happen when querying Algolia. If you want to learn more about custom widgets, check out the guide.

1
2
3
4
5
6
7
8
9
10
11
12
const search = instantsearch({
  /* Don't forget to provide your search client */
});

search.addWidgets([{
  init({ helper }) {
    helper.on('error', (error) => {
      alert('Error');
      console.error(error);
    }
  }
}]);

Of course, this is a pretty naive approach to error handling:

  • the message is not meaningful
  • the UI is completly blocked by the alert (and it is clearly foreign to your UI)

That being said, here are some ways how to improve such an experience:

  • use a friendly overlay that doesn’t break your experience
  • figure out if the user device is online
  • try to log the error on your servers (if the user is online)

Did you find this page helpful?