UI libraries / Angular InstantSearch / Widgets

Angular InstantSearch isn’t compatible with Angular’s Ivy view engine. We’re investigating how best to support this. For more information and to vote for Algolia’s support of Angular 16 and beyond, see the GitHub issue Algolia Support for Angular InstantSearch

Signature
<ais-search-box
  // Optional parameters
  placeholder="string"
  submitTitle="string"
  resetTitle="string"
  [searchAsYouType]="boolean"
  [autofocus]="boolean"
  [showLoadingIndicator]="boolean"
></ais-search-box>
Import
1
2
3
4
5
6
7
8
import { NgAisSearchBoxModule } from 'angular-instantsearch';

@NgModule({
  imports: [
    NgAisSearchBoxModule,
  ],
})
export class AppModule {}

1. Follow additional steps in Optimize build size to ensure your code is correctly bundled.
2. This imports all the widgets, even the ones you don’t use. Read the Getting started guide for more information.

About this widget

The ais-search-box widget is used to let users set a text-based query.

This usually is the main entry point to start search in an InstantSearch context. Most of the time, it is placed at the top of a search experience, so that users can start searching right away.

Examples

1
<ais-search-box></ais-search-box>

Props

Parameter Description
placeholder
type: string
default: Search
Optional

The input placeholder.

1
2
3
<ais-search-box
  placeholder="Search for products..."
></ais-search-box>
submitTitle
type: string
default: Submit
Optional

The submit button text.

1
2
3
<ais-search-box
  submitTitle="Go"
></ais-search-box>
resetTitle
type: string
default: Reset
Optional

The clear button text.

1
2
3
<ais-search-box
  resetTitle="Clear"
></ais-search-box>
searchAsYouType
type: boolean
default: true
Optional

Whether a search needs to be made on every change to the query. If false, new searches are only triggered by clicking the search button or by pressing the Enter key while the search box is focused.

1
2
3
<ais-search-box
  [searchAsYouType]="false"
></ais-search-box>
autofocus
type: boolean
default: false
Optional

Whether to automatically focus on the input when rendered.

1
2
3
<ais-search-box
  [autofocus]="true"
></ais-search-box>
showLoadingIndicator
type: boolean
default: true
Optional

Displays an indicator that the search is loading. The loading indicator is only shown if Algolia doesn’t return the search results within a time limit. On faster network connections, this avoids unnecessarily rendering the loading indicator on every keystroke, while on slower connections, it provides good user feedback. You can adjust the time limit before rendering the loading indicator with the stalledSearchDelay parameter on the ais-instantsearch component.

1
2
3
<ais-search-box
  [showLoadingIndicator]="false"
></ais-search-box>

HTML output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div class="ais-SearchBox">
  <form class="ais-SearchBox-form" novalidate>
    <input class="ais-SearchBox-input" autocomplete="off" autocorrect="off" autocapitalize="off" placeholder="Search for products" spellcheck="false" maxlength="512" type="search" value="" />
    <button class="ais-SearchBox-submit" type="submit" title="Submit the search query.">
      <svg class="ais-SearchBox-submitIcon" xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 40 40">
        ...
      </svg>
    </button>
    <button class="ais-SearchBox-reset" type="reset" title="Clear the search query." hidden>
      <svg class="ais-SearchBox-resetIcon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="10" height="10">
        ...
      </svg>
    </button>
    <span class="ais-SearchBox-loadingIndicator" hidden>
      <svg width="16" height="16" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke="#444" class="ais-SearchBox-loadingIcon">
        ...
      </svg>
    </span>
  </form>
</div>

Customize the UI with connectSearchBox

If you want to create your own UI of the ais-search-box widget, you can combine the connectSearchBox connector with the TypedBaseWidget class.

1. Extend the TypedBaseWidget class

First of all, you will need to write some boilerplate code to initialize correctly the TypedBaseWidget class. This happens in the constructor() of your class extending the TypedBaseWidget class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { Component, Inject, forwardRef, Optional } from '@angular/core';
import { TypedBaseWidget, NgAisInstantSearch, NgAisIndex } from 'angular-instantsearch';

@Component({
  selector: 'app-search-box',
  template: '<p>It works!</p>'
})
export class SearchBox extends TypedBaseWidget {
  constructor(
    @Inject(forwardRef(() => NgAisIndex))
    @Optional()
    public parentIndex: NgAisIndex,
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchInstance: NgAisInstantSearch
  ) {
    super('SearchBox');
  }
}

There are a couple of things happening in this boilerplate:

  • create a SearchBox class extending TypedBaseWidget
  • reference the <ais-instantsearch> parent component instance on the SearchBox widget class
  • set app-search-box as a selector, so we can use our component as <app-search-box></app-search-box>

2. Connect your custom widget

The TypedBaseWidget class has a method called createWidget() which takes two arguments: the connector to use and an object of options (instance options) for this connector. We call this method at ngOnInit. This component now implements OnInit.

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
import { Component, Inject, forwardRef, Optional } from '@angular/core';
import { TypedBaseWidget, NgAisInstantSearch, NgAisIndex } from 'angular-instantsearch';

import connectSearchBox, {
  SearchBoxWidgetDescription,
  SearchBoxConnectorParams
} from 'instantsearch.js/es/connectors/search-box/connectSearchBox';

@Component({
  selector: 'app-search-box',
  template: '<p>It works!</p>'
})
export class SearchBox extends TypedBaseWidget<SearchBoxWidgetDescription, SearchBoxConnectorParams> {
  public state: SearchBoxWidgetDescription['renderState']; // Rendering options
  constructor(
    @Inject(forwardRef(() => NgAisIndex))
    @Optional()
    public parentIndex: NgAisIndex,
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchInstance: NgAisInstantSearch
  ) {
    super('SearchBox');
  }
  ngOnInit() {
    this.createWidget(connectSearchBox, {
      // instance options
    });
    super.ngOnInit();
  }
}

3. Render from the state

Your component instance has access to a this.state property which holds the rendering options of the widget.

public state: SearchBoxWidgetDescription['renderState'];
// {
//   query: string;
//   refine: Function;
//   clear: Function;
//   isSearchStalled: boolean;
//   widgetParams: object;
// }
1
2
3
4
5
6
<input
  type="text"
  #input
  (keyup)="this.state.refine(input.value)"
  [value]="this.state.query"
/>

Rendering options

Parameter Description
query
type: string

The query from the current search.

refine
type: function

Sets a new query and triggers a new search.

clear
type: function

Removes the query and triggers a new search.

isSearchStalled
type: boolean

Returns true if the search results take more than a certain time to come back from Algolia servers. This can be configured on the instantsearch constructor with the stalledSearchDelay attribute.

widgetParams
type: object

All original widget options forwarded to the render function.

Instance options

Parameter Description
queryHook
type: function
Optional

A function that is called just before the search is triggered. It takes two arguments:

  • query: string: the current query string
  • search: function: triggers the search

If the search method is not called, no search is made to Algolia and the UI doesn’t refresh. If the search method is called, the widget is rendered.

This can be useful if you need to:

  • Debounce the number of searches done from the searchBox. You can find more information in the guide on slow network.
  • Programmatically alter the query.

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
32
33
34
35
36
37
import { Component, Inject, forwardRef, Optional } from '@angular/core';
import { TypedBaseWidget, NgAisInstantSearch, NgAisIndex } from 'angular-instantsearch';

import connectSearchBox, {
  SearchBoxWidgetDescription,
  SearchBoxConnectorParams
} from 'instantsearch.js/es/connectors/search-box/connectSearchBox';

@Component({
  selector: 'app-search-box',
  template: `
<input
  type="text"
  #input
  (keyup)="this.state.refine(input.value)"
  [value]="this.state.query"
/>
`
})
export class SearchBox extends TypedBaseWidget<SearchBoxWidgetDescription, SearchBoxConnectorParams> {
  public state: SearchBoxWidgetDescription['renderState']; // Rendering options
  constructor(
    @Inject(forwardRef(() => NgAisIndex))
    @Optional()
    public parentIndex: NgAisIndex,
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchInstance: NgAisInstantSearch
  ) {
    super('SearchBox');
  }
  ngOnInit() {
    this.createWidget(connectSearchBox, {
      // instance options
    });
    super.ngOnInit();
  }
}
Did you find this page helpful?