Building Autocomplete Search Component from Scratch: Angular

Shilpa Syal
5 min readJul 1, 2022

--

Photo by Safar Safarov on Unsplash

In this article, you’ll learn how to implement your own autocomplete component using Angular and RXJS. For the demo, I’ll pass an array to the suggestion options. You can also get the options from an HTTP request through API. You have a choice for the options shown. Just fetch the options and store them into an array.

So by the end of this article, we will create something like this

AutoComplete Search Input Box Example

Project Structure

Project structure of Autocomplete App

The autocomplete.component.html will render the Autocomplete component and for our demo, we will render the AutocompleteComponent in AppComponent (app.component.html).

Autocomplete Component

Let's start by creating a search input box in autocomplete.component.html like below.

<input id="car" #carSearchInput placeholder="Search Car By Name" type="text" autocomplete="off">

To grab the user input, we declare a template/local reference variable named #carSearchInput (reference variables are declared using hash symbol #) in autocomplete template.

We will use ViewChild decorator to reference it inside our autocomplete component class to access the input field properties.

@ViewChild('carSearchInput') carInput: ElementRef;

The carSearchInput reference is stored in the carInput variable of type ElementRef. After that, we can use this.carInput anywhere inside the Component.

Adding Keyup Event Listener

The keyup listener will be added to the input field using rxjs Observable fromEvent method on carInput variable which can notify us of changing text.

fromEvent accepts as a first argument event target, which is an object with methods for registering event handler functions. As a second argument, it takes a string that indicates the type of event we want to listen for. fromEvent returns Observable to which we can subscribe to listen the changes on input box.

Syntax: fromEvent(target: FromEventTarget<T>, eventName: string): Observable<T>

cars: Array that contains initial options

showSearches: (Boolean true/false) To show/hide Options div

isSearching: (Boolean true/ false) To show the user that search is in progress

searchedCars: Array of filtered items that match the user input

In the carSearch method, the keyup event listener and some more functionality is added. Let’s go through the carSearch function line by line.

  • First of all, the keyup event listener is added on the input box. As the input box reference is stored in carInput variable, we can access the underlying properties of that specific referenced element using nativeElement property.
  • As every keyup will emit KeyBoardEvent,we will extract the value entered by the user using the map operator.
  • debounceTime is the delay time and it will only emit the value after a particular time span that has been passed to it. It is used here because imagine if the output is going to API instead of local Array file then our API would be loaded with unnecessary requests for every keyup and that’s not good. So we will use debounceTime to fix this problem. Now the request to API will be performed only after a specific interval of time.
  • distinctUntilChanged method will only emit value if the current value is different from the previously emitted value.
  • switchMap is used to make a call to the filter function. If the input is empty then all the Observable of all the items will be returned otherwise filter function will be called. We will the getCars() function in detail in the next section.

switchMap will automatically unsubscribe from any previous observable when a new event comes down the stream.On each emission the previous inner observable (the result of the function you supplied) is cancelled and the new observable is subscribed. This works perfect with our example because we no longer concerned with the response of the previous request when a new input arrives.

  • We used the tap method to assign values to some variables. isSearching variable is set to true when the search starts and false when the search ends. The showSearches variable is used to show the list of searched items.

The observable returned by fromEvent is stored in the search variable. The search variable is subscribed to get back the desired result.

Now implement the filter function logic. See the code snippet below.

Here the getCars() function return the Observable of filtered Items. Therefore, when we subscribe to the search$ Observable in carSearch method, it will receive the data returned from the getCars() method like below.

search$.subscribe(data => {
this.isSearching = false
this.searchedCars = data;
})

Now let’s implement the dropdown where the filtered items will be shown.

At line 10 , items are generated by iterating over the searchedCars array. DropDown list will be hidden initially and when the user will click the item in the list. The showSearches variable is used to show and hide the dropdown list. If nothing matched with the user input, the line 14 will be executed.

At last, our autocomplete Component class will look like below

On Click on Option

When item in the dropdown will be clicked, setCarName function will be fired. This function will turn the options/suggestions off and set the selected item into the input field and will also emit the value to the parent component.

Now in the parent component class, app.component.html embed the autocomplete component selector like below

The AutocompleteComponent is placed inside of theAppComponent (Parent Component) and (setCarNameEvent)="setCarName($event)” event is added as we are telling the AppComponent to detect an event from the AutoCompleteComponent with the name "setCarNameEvent".

@Output() setcarNameEvent = new EventEmitter<{name: string}>();

this.setcarNameEvent.emit({name});

@Output() setcarNameEvent = new EventEmitter<{name: string}>(); declares the output variable setcarNameEvent as an EventEmitter , it is a built-in class used to emit custom Events.

Finally, setCarName() function will be used to fire the setcarNameEvent event, sending the `name` value of child Autocomplete component to the parent App Component.

When the setCarNameEventevent occurs, it will fire the setCarName($event)function we wrote with the $event being the passed variable, we fetch the name of the selected car and display it onto the screen.

And that’s it. We have created a simple reusable autocomplete component in Angular. Just create a different component for Autocomplete Search bar and embed it where you want its functionality. For a full example, Checkout my GitHub repository.

☕ Elevate the Journey:

If you appreciate the insights shared in my content and wish to support the journey, treat me to a coffee! Your contribution propels more coding adventures ahead. Buy Me a Coffee.

--

--

Shilpa Syal

Full Stack Developer💻 👩‍💻 Helping and Teaching others is the best way to learn