Concepts / Building Search UI / Autocomplete
May. 10, 2019

Autocomplete

You are reading the documentation for Angular InstantSearch v3, which is in beta. You can find the v2 documentation here.

Overview

A common pattern in search is to implement a search box with an autocomplete as a first step of the search experience. Angular InstantSearch doesn’t come with a built-in widget for the autocomplete. But you can create your using the BaseWidget class and autocomplete connector.

In this guide we will cover a search box which displays an autocomplete menu linked to a results page.

We won’t cover the usage of the connector in a multi-index context in this guide. There is a dedicated section about that in the multi-index search guide. You can find the source code of both examples on GitHub.

Results page with autocomplete

This is focused on integrating an ais-search-box with an autocomplete linked to a results page. To implement this we use the component Autocomplete provided by Angular Material. Once we have this component, we need to connect it with our autocomplete component. The component exposes three interesting props for this use case: indices, and refine. indices contains the list of suggestions, and refine is a function that takes a query to retrieve our relevant suggestions.

$
ng add @angular/material
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// app.module.ts
import { NgAisModule } from 'angular-instantsearch';
import { MatInputModule, MatAutocompleteModule } from '@angular/material/autocomplete';
// make sure you have BrowserAnimationsModule
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';

@NgModule({
 declarations: [
   AppComponent,
 ],
 imports: [
   BrowserModule, BrowserAnimationsModule, NgAisModule.forRoot(),
   MatInputModule, MatAutocompleteModule,
 ],
 providers: [],
 bootstrap: [AppComponent],
})
export class AppModule {}

Now add an app-autocomplete component extending BaseWidget and using and Autocomplete connector.

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
import { Component, Inject, forwardRef, Input } from '@angular/core';
import { BaseWidget, NgAisInstantSearch } from 'angular-instantsearch';
import { connectAutocomplete } from 'instantsearch.js/es/connectors';

@Component({
  selector: 'app-autocomplete',
  template: `
    <div>
      <input matInput placeholder="State" aria-label="State" [matAutocomplete]="auto" #box>
      <mat-autocomplete #auto="matAutocomplete">
        <mat-option *ngFor="let options of (state.indices && state.indices.length > 0 ? state.indices[0].hits : [])" [value]="options.name">
          <div>
            {{options.name}}
          </div>
        </mat-option>
       </mat-autocomplete>
    </div>
  `,
})
export class Autocomplete extends BaseWidget {
  state: {
    query: string;
    refine: Function;
  };

  constructor(
    @Inject(forwardRef(() => NgAisInstantSearch))
    public instantSearchParent
  ) {
    super('Autocomplete');
  }

  public handleChange(value: string) {
    this.state.refine(value);
  }

  public ngOnInit() {
    this.createWidget(connectAutocomplete, {});
    super.ngOnInit();
  }
}

When we have our autocomplete component set up we can integrate it in our application. But for that we need to use two instances of InstantSearch. We use two instances because it allows us to configure the number of hits retrieved by the autocomplete differently than the number of results. The huge benefit of it is also to not have the query tied to both instances at the same time. It allows us to clear the suggestions but sill have the query applied on the second instance. Since we have two instances we need a way to sync the query between the two. We use the ais-configure to achieve this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ais-instantsearch
    [config]="{
      appId: 'latency',
      apiKey: '6be0576ff61c053d5f9a3225e2a90f76',
      indexName: 'instant_search'
    }"
  >
  <ais-configure [searchParameters]="{ hitsPerPage: 5 }" > </ais-configure>
  <app-autocomplete></app-autocomplete>
</ais-instantsearch>

<ais-instantsearch
    [config]="{
      appId: 'latency',
      apiKey: '6be0576ff61c053d5f9a3225e2a90f76',
      indexName: 'instant_search'
    }"
  >
  <ais-configure [searchParameters]="{ hitsPerPage: 20 }" > </ais-configure>
  <ais-hits> <!-- ... --> </ais-hits>
</ais-instantsearch>

That’s it! You can find the complete example on GitHub.

Did you find this page helpful?