API Reference / InstantSearch.js Widgets / answers
Widget signature
instantsearch.widgets.EXPERIMENTAL_answers({
  container: string|HTMLElement,
  queryLanguages: string[],
  // Optional parameters
  attributesForPrediction: string[],
  nbHits: number,
  renderDebounceTime: number,
  searchDebounceTime: number,
  escapeHTML: boolean,
  extraParameters: object,
  templates: object,
  cssClasses: object,
});

About this widget

The answers widget enables semantic search on an existing index. It lets you bring your users directly to the part of your content that answers their questions.

The public API of this widget may change in the near future. Thus, there is the EXPERIMENTAL_ prefix.

Examples

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  container: '#answers',
  queryLanguages: ['en'],
});

Options

container
type: string|HTMLElement
Required

The CSS Selector or HTMLElement to insert the widget into.

1
2
3
instantsearch.widgets.EXPERIMENTAL_answers({
  container: '#answers',
});
queryLanguages
type: string[]
Required

The languages in the query. Only supports en.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  queryLanguages: ['en'],
});
attributesForPrediction
type: string[]
default: ["*"]
Optional

Attributes to use for predictions. If using the default (["*"]), all attributes are used to find answers.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  attributesForPrediction: ['description'],
});
nbHits
type: number
default: 1
Optional

Maximum number of answers to retrieve from the Answers Engine. Can’t be greater than 1000.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  nbHits: 1,
});
searchDebounceTime
type: number
default: 100
Optional

Search debounce time in milliseconds.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  searchDebounceTime: 100,
});
renderDebounceTime
type: number
default: 100
Optional

Render debounce time in milliseconds.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  renderDebounceTime: 100,
});
escapeHTML
type: boolean
default: true
Optional

Whether to escape HTML tags in a hit’s string values.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  escapeHTML: true,
});
extraParameters
type: object
Optional

Extra parameters to pass to the findAnswers method.

1
2
3
4
5
6
7
8
9
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  extraParameters: {
    threshold: 0.1,
    searchParameters: {
      filters: [...],
    },
  },
});
templates
type: object
Optional

The templates to use for the widget.

1
2
3
4
5
6
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  templates: {
    // ...
  },
});
cssClasses
type: object

The CSS classes to override.

  • root: the root element of the widget.
  • emptyRoot: the wrapping element when no results.
  • header: the header.
  • loader: the loader.
  • list: the list of results.
  • item: each result.
1
2
3
4
5
6
7
8
9
10
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  cssClasses: {
    root: 'MyCustomAnswers',
    header: [
      'MyCustomAnswersHeader',
      'MyCustomAnswersHeader--subclass',
    ],
  },
});

Templates

header
type: string|function
Optional

Template to use for the header. This template receives an object containing hits and isLoading.

1
2
3
4
5
6
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  templates: {
    header: 'Header',
  },
});
loader
type: string|function
Optional

Template to use for the loader.

1
2
3
4
5
6
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  templates: {
    loader: 'Loading...'
  },
});
item
type: string|function
Optional

Template to use for each result. This template receives an object containing a single record.

1
2
3
4
5
6
7
8
9
10
11
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  templates: {
    item: `
      <h2>
        {{#helpers.highlight}}{ "attribute": "name" }{{/helpers.highlight}}
      </h2>
      <p>{{ description }}</p>
    `,
  },
});

HTML output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="ais-Answers">
  <div class="ais-Answers-header">
    ...
  </div>
  <div class="ais-Answers-loader">
    ...
  </div>
  <ul class="ais-Answers-list">
    <li class="ais-Answers-item">
      ...
    </li>
    <li class="ais-Answers-item">
      ...
    </li>
    ...
  </ul>
</div>

Customize the UI - connectAnswers

If you want to create your own UI of the answers widget, you can use connectors.

It’s a 3-step process:

// 1. Create a render function
const renderAnswers = (renderOptions, isFirstRender) => {
  // Rendering logic
};

// 2. Create the custom widget
const customAnswers = instantsearch.connectors.connectAnswers(
  renderAnswers
);

// 3. Instantiate
search.addWidgets([
  customAnswers({
    // instance params
  })
]);

Create a render function

This rendering function is called before the first search (init lifecycle step) and each time results come back from Algolia (render lifecycle step).

const renderAnswers = (renderOptions, isFirstRender) => {
  const {
    array hits,
    boolean isLoading,
  } = renderOptions;

  if (isFirstRender) {
    // Do some initial rendering and bind events
  }

  // Render the widget
}

Render options

hits
type: array

The matched hits from the Algolia engine.

1
2
3
4
5
6
7
const renderAnswers = (renderOptions, isFirstRender) => {
  const { hits } = renderOptions;

  const container = document.querySelector('#answers');

  container.innerHTML = hits.map(hit => hit.name).join('<br />');
};
isLoading
type: boolean

Whether the Answers API is still loading the results.

1
2
3
4
5
6
7
8
const renderAnswers = (renderOptions, isFirstRender) => {
  const { isLoading, hits } = renderOptions;

  const container = document.querySelector('#answers');

  container.innerHTML = isLoading ?
    'Loading ...' : hits.map(hit => hit.name).join('<br />');
};
widgetParams
type: object

All original widget options forwarded to the render function.

1
2
3
4
5
6
7
8
9
10
11
12
13
const renderRangeInput = (renderOptions, isFirstRender) => {
  const { widgetParams } = renderOptions;

  widgetParams.container.innerHTML = '...';
};

// ...

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

Create and instantiate the custom widget

We first create custom widgets from our rendering function, then we instantiate them. When doing that, there are two types of parameters you can give:

  • Instance parameters: they are predefined parameters that you can use to configure the behavior of Algolia.
  • Your own parameters: to make the custom widget generic.

Both instance and custom parameters are available in connector.widgetParams, inside the renderFunction.

const customAnswers = instantsearch.connectors.connectAnswers(
  renderAnswers
);

search.addWidgets([
  customAnswers({
    queryLanguages: string[],
    attributesForPrediction: string[],
    nbHits: number,
    searchDebounceTime: number,
    renderDebounceTime: number,
    escapeHTML: boolean,
    extraParameters: object,
    // Optional parameters
    // ...
  })
]);

Instance options

queryLanguages
type: string[]
Required

The languages in the query. Only supports en.

1
2
3
4
customAnswers({
  // ...
  queryLanguages: ['en'],
});
attributesForPrediction
type: string[]
default: ["*"]
Optional

Attributes to use for predictions. If using the default (["*"]), all attributes are used to find answers.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  attributesForPrediction: ['description'],
});
nbHits
type: number
default: 1
Optional

Maximum number of answers to retrieve from the Answers Engine. Can’t be greater than 1000.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  nbHits: 1,
});
searchDebounceTime
type: number
default: 100
Optional

Search debounce time in milliseconds.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  searchDebounceTime: 100,
});
renderDebounceTime
type: number
default: 100
Optional

Render debounce time in milliseconds.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  renderDebounceTime: 100,
});
escapeHTML
type: boolean
default: true
Optional

Whether to escape HTML tags in a hit’s string values.

1
2
3
4
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  escapeHTML: true,
});
extraParameters
type: object
Optional

Extra parameters to pass to the findAnswers method.

1
2
3
4
5
6
7
8
9
instantsearch.widgets.EXPERIMENTAL_answers({
  // ...
  extraParameters: {
    threshold: 0.1,
    searchParameters: {
      filters: [...],
    },
  },
});

Full example

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
// Create a render function
const renderAnswers = (renderOptions, isFirstRender) => {
  const { hits, isLoading } = renderOptions;

  widgetParams.container.innerHTML = isLoading ? 
    '<p>Loading...</p>'
    : `
      <ul>
        ${hits
          .map(
            item =>
              `<li>
                ${instantsearch.highlight({ attribute: 'name', hit: item })}
              </li>`
          )
          .join('')}
      </ul>
    `;
};

// create custom widget
const customAnswers = instantsearch.connectors.connectAnswers(
  renderAnswers
);

// instantiate custom widget
search.addWidgets([
  customAnswers({
    container: document.querySelector('#answers'),
  })
]);

Did you find this page helpful?