Thank you for reading my blog posts, I am no longer publishing new content on this platform. You can find my latest content on either mainawycliffe.dev or All Things Typescript Newsletter (✉️)
In this demo, we will build an angular autocomplete component that gets autocomplete suggestions from a http service such as a REST API. The idea here is that, instead of using a static autocomplete list, we are going to pull autocomplete suggestions directly from our database. This is a neat feature to have especially if you are implementing a search function in your angular app.
First, I am going to assume that, you have some basic knowledge on both Angular and Angular 2 Material. If you are new to this, please check out the tutorials on Angular here and Angular 2 Material here.
In this demo, we will create a simple search for Github repositories. You enter the name of a repository and get the results. Then you can use the results (list of repositories matching the name you entered) as a autocomplete options. Github API provides the option to retrieve results for unauthenticated users, you can learn more here.
Make sure you have imported all Angular Material Modules you need for your specific project. In this project we will be using MatAutocompleteModule
, MatFormFieldModule
and MatInputModule
.
So, without further ado, let’s get into the code:
We are going to create a service that will interact with the Github API. It will make HTTP calls to the API and return an observable of the search results. To make things easier, we will also create an interface – GithubResponse
– that we can use to type cast our results we expect from github. Please checkout out the interface details here.
First, Let’s look at our service.
// github.service.ts
export class GithubService {
constructor(private http: HttpClient) {}
search(query: string): Observable<GithubResponse> {
const url = 'https://api.github.com/search/repositories';
return this.http
.get<GithubResponse>(url, {
observe: 'response',
params: {
q: query,
sort: 'stars',
order: 'desc'
}
})
.pipe(
map((res: Response) => {
return res.body;
})
);
}
}
It has a single method, that takes in the search query and returns the results. This is your normal service and doesn’t do anything special.
In our component, we will need an observable Property - GithubAutoComplete$
- which we can subscribe to using async pipe, so that it can always have the latest values of our autocomplete options. So, we shall first subscribe to the autocomplete form control value changes, then use the value of the autocomplete form control as the query for our search method. And then we shall return the results to the GithubAutoComplete$
property of our component.
First, declare a GithubAutoComplete$
and our form control property - autoCompleteControl
:
public githubAutoComplete$: Observable<Items> = null;
public autoCompleteControl = new FormControl();
Then, let’s create a lookup method that maps the results from github to an object we can use and catch errors.
lookup(value: string): Observable<Items> {
return this.githubService.search(value.toLowerCase()).pipe(
// map the item property of the github results as our return object
map(results => results.items),
// catch errors
catchError(_ => {
return of(null);
})
);
}
And then, on component initialization (ngOnInit
Method), assign our GithubAutoComplete$
to the observable of the valueChanges
of our input form control.
ngOnInit() {
this.githubAutoComplete$ = this.autoCompleteControl.valueChanges.pipe(
startWith(''),
// delay emits
debounceTime(300),
// use switch map so as to cancel previous subscribed events, before creating new once
switchMap(value => {
if (value !== '') {
// lookup from github
return this.lookup(value);
} else {
// if no value is present, return null
return of(null);
}
})
);
}
NB: Please read through the comments for further code clarification. And finally, in our template, we use async pipe to subscribe to the GithubAutoComplete$
observable inside *ngFor
as shown below.
<mat-form-field>
<input [formControl]="autoCompleteControl" type="text" placeholder="Pick one" aria-label="Number" matInput [matAutocomplete]="auto">
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option ***ngFor****=****"let item of githubAutoComplete$ | async; let index = index"** [value]="item.name">
{{ item.name | titlecase}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
And that’s it, a working Angular 2 Material Autocomplete which works with a HTTP Service.
NB: Remember to implement OnInit interface on your component to run the ngOnInit
method on component initialization.
You can find a demo to tryout with here and the source code here.
Thank you for getting this far on this post, I hope this was helpful. If I missed anything or something was not clear, please tell me on the comment section below. Here are some more topics on Angular:
UI Libraries and Frameworks make it easier for developers to build clean and consistent User Interfaces (UI). They provide components, …
Read MoreAngular material has a very nice date picker but while its functionality can accommodate a lot of developers, sometimes it just falls short. …
Read MoreOne of the least talked about features of Angular 6 is Angular CLI Workspaces. Workspaces or Angular CLI Workspaces give angular developers …
Read MoreIcons are a necessity when building modern-day web apps and sometimes they can be frustrating. While icon sets like Font Awesome and …
Read MoreToday, we are going to create a responsive Navbar using Toolbar and Sidenav Components from Angular Material together with Angular Flex …
Read MoreA couple months ago, I was having a debate on whether I should switch from Bootstrap to Angular Material. I have used Bootstrap for a very …
Read More