Angular material autocomplete example

An Angular material is an amazing UI for Angular framework, it has lots of pre-built components like card, modal, more, and Angular material expansion panel or Angular material autocomplete is one of them.

In this tutorial, first will learn how to use Angular material autocomplete component and second how to use Angular material autocomplete with API call. Let’s get started.

Step 1: Setting up and configure Angular material autocomplete project

Let first create our Angular material autocomplete project and we have two examples of it. Before starting an angular project you need to install nodejs and Angular CLI in your system.

ng new autoCompleteeApp
cd autoCompleteeApp
ng add @angular/material

While running the 3rd command will ask you the select theme, material typography, and animation, press yes on all. To use the Angular material component, we have to import it into our app module. Let create a module and import all material components on it.

ng g m ng-material
Angular material autocomplete

To use the Angular material accordion, we need to import MatExpansionModule in our custom module. It is up to you to add all material modules in a separate custom module or root module app. We are adding all material modules in a custom module, it containing only the material module.

Open src/app/ng-material/ng-material.module.ts and replace the existing code with the code shown below and we need the following material component for our example.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';


@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    MatAutocompleteModule,
    MatFormFieldModule,
    MatInputModule
  ],
  exports: [
    MatAutocompleteModule,
    MatFormFieldModule,
    MatInputModule
  ]
})
export class NgMaterialModule { }

We are importing all the required modules in our custom material module file and keeping separate modules for Angular material will make the application easy to maintain. We also need to Form and HttpClient module to demonstrate Angular material autocomplete or angular material typeahead. Now we need to import our material module in the src/app/app.module.ts file.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgMaterialModule } from './ng-material/ng-material.module';
import { HttpClientModule } from '@angular/common/http'
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    FormsModule,
    ReactiveFormsModule,
    NgMaterialModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

To demonstrate the material list we need dummy data, create folder data in assets and states.json file and add the following dummy data.

{
    "states": [
        { "name": "Alabama" },
        { "name": "Alaska" },
        { "name": "Arizona" },
        { "name": "Arkansas" },
        { "name": "California" },
        { "name": "Colorado" },
        { "name": "Connecticut" },
        { "name": "Delaware" },
        { "name": "Florida" },
        { "name": "Georgia" },
        { "name": "Hawaii" },
        { "name": "Idaho" }
    ]
}

Step 2 : Angular material autocomplete example

We have completed the configuration of the project, let us demonstrate our first example that uses most of the components and directives needed for creating an Angular material expansion panel. Here is a screenshot of our first example.

Angular material autocomplete example

Let edit the app.component.html template to add our Angular material autocomplete component.

<div class="container">
  <section>
    <form class="example-form">
      <mat-form-field class="example-full-width" appearance="fill">
        <mat-label>Angular Material autocomplete</mat-label>
        <input type="text"
               placeholder="Select country"
               aria-label="Country"
               matInput
               [formControl]="myControl"
               [matAutocomplete]="auto">
        <mat-autocomplete autoActiveFirstOption
           #auto="matAutocomplete">
          <mat-option *ngFor="let option of countryFilteredOptions | async" 
           [value]="option">
            {{option}}
          </mat-option>
        </mat-autocomplete>
      </mat-form-field>
    </form>
  </section>

<router-outlet></router-outlet>
</div>
import { Component } from '@angular/core';
import { FormControl, FormBuilder } from '@angular/forms';
import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  myControl = new FormControl();
  coutries: string[] = ['France', 'India', 'USA', 'Germany', 'Japan'];
  countryFilteredOptions: Observable<string[]> | undefined;


  constructor(private formBuilder: FormBuilder) {}

  ngOnInit(): void {
    this.countryFilteredOptions = this.myControl.valueChanges.pipe(
      startWith(''),
      map(value => this._filter(value))
    );
  }


  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();

    return this.coutries.filter(country => 
       country.toLowerCase().includes(filterValue));
  }
}

Angular material autocomplete properties

Angular material typeahead component has component and sub-component. Here have listed some of the mat autocomplete components.

NameProperties
mat-autocompleteThe mat-autocomplete is a root container containing a list of options. We can add data binding and formControl on it.
mat-optionSub-component of mat-select and we add individual option item of unique value on it.
mat-optgroupOptional sub-component of mat-select and we can group related options.
autoThe auto attribute needs to link input with autocomplete component by passing the reference of the input element.

Angular material autocomplete with API call

We’ll demonstrate Angular material autocomplete with API call using HTTP GET method. We have already created a typeahead service to retrieve our dummy data. Here is a screenshot.

Angular material autocomplete with API call

Let add the mat autocomplete component in our template, edit the app.component.html file.

<div class="container">
  <section>
    <mat-form-field>
      <input type="text" placeholder="Enter state" [formControl]="myControl" 
        matInput [matAutocomplete]="auto">
      <mat-autocomplete #auto="matAutocomplete">
        <mat-option *ngFor="let option of filterRegions | async" 
         [value]="option.name">
          {{option.name}}
        </mat-option>
      </mat-autocomplete>
    </mat-form-field>
   </section>

   <router-outlet></router-outlet>
</div>
import { Component } from '@angular/core';
import { FormGroup, FormControl, FormBuilder } from '@angular/forms';
import { Observable } from 'rxjs';
import { TypeaheadService } from './services/typeahead.service';
import { distinctUntilChanged, startWith, switchMap } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  myControl = new FormControl();
  form!: FormGroup;
  filterRegions: Observable<any> | undefined;
  data: string[] = [];

  constructor(private formBuilder: FormBuilder,
    private http: HttpClient,
    private typeahead: TypeaheadService) {
    this.filterRegions = this.myControl.valueChanges.pipe(
      startWith(''),
      distinctUntilChanged(),
      switchMap((name: string) => {
        return this.typeahead.getStates(name)
      })
    )
  }
}

Create autocomplete service

We need to create a service called the typeahead.service.ts in the services folder by running the following command.

ng g service services/typeahead

In a real application, we might use angular material autocomplete at any part of the application. We need to have a service for angular autocomplete and in our example, we have used autocomplete of one data source. In typeahead.service.ts file edit service to retrieve, filter Angular autocomplete task.

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class TypeaheadService {
  constructor(private http: HttpClient) { }

  getStates(term: string): Observable<string[]> {
    return new Observable((observer) => {
      let getStatesNamePromise: Promise<any>;

      getStatesNamePromise = new Promise((resolve) => {
        this.http.get<string[]>('./assets/data/states.json')
         .subscribe((data: any) => {
          resolve(data.states);
        });
      });

      getStatesNamePromise.then((data) => {
        if (term) {
          data = data.filter((x: any) =>
            x.name.toLocaleLowerCase().indexOf(term.toLocaleLowerCase()) > -1);
        }
        observer.next(data);
      });
    });
  }
}

Angular material autocomplete example with image

Angular material autocomplete example with image

Angular material autocomplete option we can add image also, here have our last example on material autocomplete.

To demonstrate this example we need dummy data, let add countries.json in our assets/data/countries.json file

[
    {
        "name": "France",
        "flag": "c/c3/Flag_of_France.svg",
        "area": 640679,
        "population": 64979548,
        "description": "France, the largest country in Western Europe"
    },
    {
        "name": "India",
        "flag": "4/41/Flag_of_India.svg",
        "area": 3287263,
        "population": 1324171354,
        "description": "India (Hindi: Bhārat), officially the Republic of India"
    },
    {
        "name": "Germany",
        "flag": "b/ba/Flag_of_Germany.svg",
        "area": 357114,
        "population": 82114224,
        "description": "Germany is a country located in the western Europe"
    }
]

Let’s edit the app.compoenent.html template.

 <section>
    <mat-form-field class="example-full-width">
      <input type="text" placeholder="Pick one" aria-label="Number" matInput [matAutocomplete]="auto"
        [formControl]="countryCtrl">
      <mat-autocomplete #auto="matAutocomplete" (keyup)="getRegions($event)">
        <mat-option *ngFor="let option of filterRegions | async" [value]="option.name">
          <img style="vertical-align:middle;" [src]="'https://upload.wikimedia.org/wikipedia/commons/' + option.flag"
            height="50" width="50" alt="country flag" />
          <span> {{ option.name }}</span> |
          <small>Population: {{ option.population}} </small>
          <small>Area : {{ option.area }}</small>
        </mat-option>
      </mat-autocomplete>
    </mat-form-field>
  </section>
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

interface Country {
  name: string;
  flag: string;
  area: number;
  population: number;
}
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  countryCtrl = new FormControl();
  filterRegions: Observable<any[]> | undefined;
  data: Country[] = [];

  constructor(
    private http: HttpClient) {

    this.http.get<Country[]>('./assets/data/countries.json')
      .subscribe((res: Country[]) => {
        this.data = res;
      });

    this.filterRegions = this.countryCtrl.valueChanges.pipe(
      startWith(''),
      map(region => region ? this.getRegions(region) : this.data.slice())
    );
  }

  getRegions(name: any): any {
    return this.data.filter((x: any) => x.name.toLocaleLowerCase().indexOf(name.toLocaleLowerCase()) > -1);
  }
}

Conclusion
We have completed our Angular material autocomplete example tutorial. We also have demonstrated how to add images or HTML elements in the material option. hope, you have got some idea.

Related Articles

Spread the love

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top