Auto-complete with material and RxJS
Tags: angular, rxjs, material, javascript
Published: 2021-07-03 14:56:36

{% github anirbmuk/AutocompleteDemo no-readme %}

This article talks about an efficient way to implement auto-complete feature using Angular concepts. The key components used in this demonstration are as follows:
&nbsp;
1. Angular Material (v15) Autocomplete module.
2. RxJS for action and data binding.

I have used [Dummy-JSON](https://dummyjson.com/) for getting fake JSON data.

![Demo1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wib80fp0et7wp32n3n0.png)

![Demo2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tvk3og4n5h23p40dncd.png)

![Demo3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3lzh7tu06czy32ht8z2t.png)

Let us now see how we go about it:
&nbsp;
#The UI:
The front-end consists of an angular autocomplete module. The input event taps the user's keystrokes and emits a new value into an action subject.

![app.component.html](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dprd527ytedk06jpsa31.png)

Each key-stroke emits a new value into an action subject declared in the `ProductService` class.

![app.component.ts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62qubq7zujucdl576sem.png)

&nbsp;
#The Service:
I selected a `Subject`, since I want it emit a value only when the user starts to type. The `action$` is an `observable` built out of this subject.

![autocomplete.service.ts 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyzdpz2hrwjv0er4vkp7.png)
&nbsp;
Every time a new value is emitted into the action stream, it returns an observable from the http `GET` request. Since this is a higher-order observable (i.e., an observable returning an observable), we make use of one of the higher order functions like `switchMap`.

![autocomplete.service.ts 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5428ppz4r7s8ynpsqztq.png)

So why `switchMap` (and not other higher order functions like `concatMap` or `mergeMap`)? The reason is: `switchMap` unsubscribes from the previous observable once a new value is emitted by the parent observable.

What this means is - as soon as the user types in another letter or removes a letter, there is simply no need to subscribe and execute the rest call for the previous values. The user is only interested to see the results of the search according to his/her current input. And `switchMap` does this automatically, and thus gets rid of unwanted rest calls.

We can also get additional control on when to fire the rest service depending on the length of the user's input. For example, in this demo, I fire the rest call only when the user has entered at least 2 characters. If not, then I return an observable of empty array (using `of([])`).

Use `distinctUntilChanged` operator to exclude user inputs which have not changed during the debounce period. So the http call will only fire for new input values, and not if the user quickly changed the input and reverted to the old value.

&nbsp;

#Back to the Component:
We tap onto the above observable and use `async pipe` to subscribe to it. Since we are completely using observables, we can also use the `OnPush` change-detection-strategy.

![app.component.html 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6mgg88d474igpfrqmi4.png)

And that is all :-)  

@angular/cli - 15.2.8
@angular/material - 15.2.9  
Source: [GitHub](https://github.com/anirbmuk/AutocompleteDemo.git)

Cheers :-)
[Anirban Mukherjee](https://anirbmuk.appspot.com/en)