Angular 8/9/10 Autocomplete Tutorial with Angular Material

Last updated on by Digamber
Today we are going to create Autocomplete in Angular 8/9/10 using Angular Material 10 UI components. The autocomplete is a functionality which shows the recommended options to the user when the user clicks on the input field or enters some keywords in an input field.

We’ll create an Angular app from scratch to show how to create the autocomplete functionality. To create autocomplete in Angular 9|10, we will set up a basic app using Angular, and then we will install and configure Angular material 8 UI framework.

Next, we’ll import MatAutocompleteModule in the app. This directive is used to build autocomplete in Angular 8/9/10. It helps user to show all the possible results, when the user types something in the input box. Then it shows the recommended options to the user in a dropdown.

Step 1: Install Angular App

Run command to install the Angular app, will show Angular 8/9/10 autocomplete here using Angular Material Autocomplete component.

ng new angular8-autocomplete-app

# ? Would you like to add Angular routing? Yes
# ? Which stylesheet format would you like to use? SCSS

Go inside the project folder.

cd angular8-autocomplete-app

Step 2: Install & Configure Angular Material

Enter the cmd to install Angular Material 8 library in autocomplete app:

ng add @angular/material

Choose Angular Material Pre-built Theme:

? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink

❯ Indigo/Pink        [ Preview: https://material.angular.io?theme=indigo-pink ] 
  Deep Purple/Amber  [ Preview: https://material.angular.io?theme=deeppurple-amber ] 
  Pink/Blue Grey     [ Preview: https://material.angular.io?theme=pink-bluegrey ] 
  Purple/Green       [ Preview: https://material.angular.io?theme=purple-green ]

Select Yes for including Angular Material Typography and Animations packages.

# ? Set up global Angular Material typography styles? Yes
# ? Set up browser animations for Angular Material? Yes

To know more about Angular Material, please visit the official angular material site here.

Step 3: Custom Angular Material Module File

Create a custom angular-material.module.ts file, In this custom angular-material module file we can import various ui components from Angular material ui library.

However, you can import only the modules you require to use such as MatAutocompleteModule and MatInputModule directives.

Go to angular-material.module.ts file and add the following code.

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { OverlayModule } from '@angular/cdk/overlay';
import { CdkTreeModule } from '@angular/cdk/tree';
import { PortalModule } from '@angular/cdk/portal';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatRippleModule } from '@angular/material/core';
import { MatDividerModule } from '@angular/material/divider';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatMenuModule } from '@angular/material/menu';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTreeModule } from '@angular/material/tree';
import { MatBadgeModule } from '@angular/material/badge';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatRadioModule } from '@angular/material/radio';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatTooltipModule } from '@angular/material/tooltip';


const materialModules = [
  CdkTreeModule,
  MatAutocompleteModule,
  MatButtonModule,
  MatCardModule,
  MatCheckboxModule,
  MatChipsModule,
  MatDividerModule,
  MatExpansionModule,
  MatIconModule,
  MatInputModule,
  MatListModule,
  MatMenuModule,
  MatProgressSpinnerModule,
  MatPaginatorModule,
  MatRippleModule,
  MatSelectModule,
  MatSidenavModule,
  MatSnackBarModule,
  MatSortModule,
  MatTableModule,
  MatTabsModule,
  MatToolbarModule,
  MatFormFieldModule,
  MatButtonToggleModule,
  MatTreeModule,
  OverlayModule,
  PortalModule,
  MatBadgeModule,
  MatGridListModule,
  MatRadioModule,
  MatDatepickerModule,
  MatTooltipModule
];

@NgModule({
  imports: [
    CommonModule,
    ...materialModules
  ],
  exports: [
    ...materialModules
  ],
})

export class AngularMaterialModule { }

Import Angular Material module file inside the app.module.ts file.

/* Angular material */
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AngularMaterialModule } from './angular-material.module';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@NgModule({
  declarations: [...],
  imports: [
    BrowserAnimationsModule,
    AngularMaterialModule,
  ],
  providers: [...],
  bootstrap: [...],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})

export class AppModule { }

Step 4: Importing Reactive Forms & FormsModule in App Module

To make the input field and dropdown menu work properly, we will import FormsModule, ReactiveFormsModule from from ‘@angular/forms’.

app.module.ts

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [...],
  imports: [
    ReactiveFormsModule,
    FormsModule
  ],
  providers: [...],
  bootstrap: [...],
  schemas: [...]
})

export class AppModule { }

Step 5: Create Autocomplete in Angular 8/9

In the below autocomplete example, we will create a simple autocomplete recommendation search bar.

Add the code in app.component.html file:

<mat-form-field>
   <input type="text" placeholder="Enter Location" matInput [formControl]="myControl"
        [matAutocomplete]="auto">
      <mat-autocomplete #auto="matAutocomplete">
        <mat-option *ngFor="let option of options" [value]="option">
          {{option}}
       </mat-option>
   </mat-autocomplete>
</mat-form-field>

Go to app.component.ts file and add the following code:

import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  myControl = new FormControl();
  options: string[] = ['Delhi', 'Mumbai', 'Banglore'];
}

Check out the autocomplete directive in action on the browser, for the autocomplete demo execute the following command

ng serve --open

Angular Material 8/0/10 Autocomplete Examples

We can try our hands on the more Angular Material 10 Autocomplete examples below:

Step 6: Create Option Groups in Autocomplete Dropdown

We can use mat-option directive to put the data into the groups using the mat-optgroup element.

Code should go in app.component.html file:

<div class="container">
  <form [formGroup]="stateForm">
    <mat-form-field>
      <input type="text" matInput placeholder="States Group" formControlName="stateGroup" required [matAutocomplete]="autoGroup">
        <mat-autocomplete #autoGroup="matAutocomplete">
          <mat-optgroup *ngFor="let group of stateGroupOptions | async" [label]="group.letter">
            <mat-option *ngFor="let name of group.names" [value]="name">
              {{name}}
            </mat-option>
        </mat-optgroup>
      </mat-autocomplete>
    </mat-form-field>
  </form>
</div>

Add code in app.component.ts file:

import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup} from '@angular/forms';
import {Observable} from 'rxjs';
import {startWith, map} from 'rxjs/operators';

export interface StateGroup {
  letter: string;
  names: string[];
}

export const _filter = (opt: string[], value: string): string[] => {
  const filterValue = value.toLowerCase();

  return opt.filter(item => item.toLowerCase().indexOf(filterValue) === 0);
};

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  stateForm: FormGroup = this._formBuilder.group({
    stateGroup: '',
  });

  stateGroups: StateGroup[] = [{
    letter: 'A',
    names: ['Alabama', 'Alaska', 'Arizona', 'Arkansas']
  }, {
    letter: 'C',
    names: ['California', 'Colorado', 'Connecticut']
  }, {
    letter: 'D',
    names: ['Delaware']
  }, {
    letter: 'F',
    names: ['Florida']
  }, {
    letter: 'G',
    names: ['Georgia']
  }, {
    letter: 'H',
    names: ['Hawaii']
  }, {
    letter: 'I',
    names: ['Idaho', 'Illinois', 'Indiana', 'Iowa']
  }, {
    letter: 'K',
    names: ['Kansas', 'Kentucky']
  }, {
    letter: 'L',
    names: ['Louisiana']
  }, {
    letter: 'M',
    names: ['Maine', 'Maryland', 'Massachusetts', 'Michigan',
      'Minnesota', 'Mississippi', 'Missouri', 'Montana']
  }, {
    letter: 'N',
    names: ['Nebraska', 'Nevada', 'New Hampshire', 'New Jersey',
      'New Mexico', 'New York', 'North Carolina', 'North Dakota']
  }, {
    letter: 'O',
    names: ['Ohio', 'Oklahoma', 'Oregon']
  }, {
    letter: 'P',
    names: ['Pennsylvania']
  }, {
    letter: 'R',
    names: ['Rhode Island']
  }, {
    letter: 'S',
    names: ['South Carolina', 'South Dakota']
  }, {
    letter: 'T',
    names: ['Tennessee', 'Texas']
  }, {
    letter: 'U',
    names: ['Utah']
  }, {
    letter: 'V',
    names: ['Vermont', 'Virginia']
  }, {
    letter: 'W',
    names: ['Washington', 'West Virginia', 'Wisconsin', 'Wyoming']
  }];

  stateGroupOptions: Observable<StateGroup[]>;

  constructor(private _formBuilder: FormBuilder) {}

  ngOnInit() {
    this.stateGroupOptions = this.stateForm.get('stateGroup')!.valueChanges
      .pipe(
        startWith(''),
        map(value => this._filterGroup(value))
      );
  }

  private _filterGroup(value: string): StateGroup[] {
    if (value) {
      return this.stateGroups
        .map(group => ({letter: group.letter, names: _filter(group.names, value)}))
        .filter(group => group.names.length > 0);
    }

    return this.stateGroups;
  }
}

Step 7: Highlight First Option in Angular 8/9 Autocomplete

In next example we are going to highlight the first option automatically in Autocomplete dropdown in Angular 8/9 option menu bar.

Code goes in app.component.html file:

<mat-form-field>
  <input type="text" placeholder="Enter City" matInput [formControl]="myControl" [matAutocomplete]="auto">
  <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
    <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
      {{option}}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

Add code in app.component.ts file:

import {Component, OnInit} from '@angular/core';
import {FormControl} from '@angular/forms';
import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  myControl = new FormControl();
  options: string[] = ['Delhi', 'Mumbai', 'Banglore'];
  filteredOptions: Observable<string[]>;

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

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

    return this.options.filter(option => option.toLowerCase().indexOf(filterValue) === 0);
  }
}

Eventually, Angular Material 10 Autocomplete Tutorial with Angular 10 examples is over.