Angular Material Autocomplete with API Call
Table of Contents
Overview
This is an example of how to build an Autocomplete Field with Angular Material. To keep this simple, we will use JSON data from a file and a service that fetches data to simulate an API call.
Please get the complete source files from https://github.com/fullstacksoup/blog-ng-material-autocomplete.git.
Get Source Files
Remember to CD into the application folder and run npm install before ng server from the root directory.
Prerequisites
Install Angular Material.
ng add @angular/material
JSON Data
Add a JSON file under the assets folder as ‘assets/state.json’.
Add the following to your JSON file. Get the full JSON file from the GitHub example.
[
{
"name": "Alabama",
"abbreviation": "AL"
},
{
"name": "Alaska",
"abbreviation": "AK"
},
{
"name": "American Samoa",
"abbreviation": "AS"
},
{
"name": "Arizona",
"abbreviation": "AZ"
},
{
"name": "Arkansas",
"abbreviation": "AR"
},
{
"name": "California",
"abbreviation": "CA"
},
{
"name": "Colorado",
"abbreviation": "CO"
}
]
HTTP Service
Next create a service for getting the country data.
ng g c services/geo-location
For geo-location-service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class GeoLocationService {
constructor(private http: HttpClient) { }
// Get JSON Data from file - states.json under src/assets/
public getStates(): Observable<any> {
return this.http.get('assets/states.json');
}
}
Autocomplete Component
Create a new component called autocomplete-field-countries.
ng g c components/json-autocomplete-field
Typescript
The autocomplete-field-states.component.ts file add the following.
import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { GeoLocationService } from 'src/app/services/geo-location.service';
import { FormControl } from '@angular/forms';
import { map, startWith } from 'rxjs/operators';
import { Observable } from 'rxjs/internal/Observable';
import { MatSnackBar } from '@angular/material/snack-bar';
export interface USStates {
name: string;
abbreviation: string;
}
@Component({
selector: 'json-autocomplete-field',
templateUrl: './json-autocomplete-field.component.html',
styleUrls: ['./json-autocomplete-field.component.scss']
})
export class JsonAutocompleteFieldComponent implements OnInit, OnDestroy{
private subs = new Subscription();
options: USStates[] = [];
filteredJSONDataOptions: Observable<any[]>;
jsonControl = new FormControl();
constructor(private geoSVC: GeoLocationService, private snackBar: MatSnackBar) {}
ngOnInit(): void {
this.subs.add(this.geoSVC.getStates().subscribe((data) => {
this.options = data;
},
(err: HttpErrorResponse) => {
console.log(err);
}));
this.filteredJSONDataOptions = this.jsonControl.valueChanges.pipe(
startWith(''),
map(value => this.json_data_filter(value))
);
}
ngOnDestroy(): void {
if (this.subs) {
this.subs.unsubscribe();
}
}
// JSON Data Filter
private json_data_filter(value: string): string[] {
const filterValue = value.toLowerCase();
let newList = [];
this.options.forEach(element => {
if (element.name.toLowerCase().indexOf(value.toLowerCase()) !== -1) {
newList.push({'name': element.name, 'abbreviation': element.abbreviation });
}
})
return newList;
}
private openSnackBar(message: string): void {
this.snackBar.open(message, 'X', {
duration: 2000,
verticalPosition: 'top'
});
}
public onSelectState(value: string): void {
this.openSnackBar(`State abbreviation selected: ${value}`)
}
}
Important: The variable holding this information should be declared as type USStates[] = [] which is defined as an interface.
options: USStates[] = [];
HTML
Add the following code to autocomplete-field-countries.component.html.
<mat-form-field>
<input type="text"
placeholder="Pick a State"
aria-label="Number"
matInput
[formControl]="jsonControl"
[matAutocomplete]="auto">
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredJSONDataOptions | async" [value]="option.name" (onSelectionChange)="onSelectState(option.abbreviation)">
{{option.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>

You must be logged in to post a comment.