HTTP GET In Angular
In this article, we will learn how to use the HttpClient module in Angular to make HTTP GET queries. In Angular 4.3, the HttpClient Module was introduced. It's included in the @angular/common/http package. Let's develop an HTTP GET example app in this article that uses the GitHub API to submit an HTTP Get request to a GitHub repository.
HTTP Get Example
Create a new Angular application using the following command:
ng new http-get
Import HttpClientModule
To initiate an HTTP Get request, we'll need to use the HttpClientModule from the @angular/common/http package. Import the app.module.ts file into your project. Import the FormsModule as well.
In the below example, you must additionally include it in the imports array.
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { FormsModule } from '@angular/forms' import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { GitHubService } from './github.service'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule, FormsModule ], providers: [GitHubService], bootstrap: [AppComponent] }) export class AppModule { }
Now, create a new model namely as repos.ts, and add the following code to the repos.ts file. For the GitHub repository, this is a simplified model.
export class repos { id: string; name: string; html_url: string; description: string; }
HTTP GET Service
Let's make a service that will handle HTTP requests. Copy the following code into a new file called github.service.ts.
import { Injectable } from '@angular/core'; import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { map, catchError} from 'rxjs/operators'; import { repos } from './repos'; @Injectable() export class GitHubService { baseURL: string = "https://api.github.com/"; constructor(private http: HttpClient) { } getRepos(userName: string): Observable<any> { return this.http.get(this.baseURL + 'users/' + userName + '/repos') } }
We begin by importing the necessary libraries. The HttpClient is the core service that handles HTTP requests such as GET, PUT, and POST. This must be injected into our GitHubService. Import HttpParams as well, which allows us to include Query Parameters in HTTP Requests. Import HTTP Headers with HttpHeaders, a function that allows us to add HTTP Headers to a request.
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
The RxJs observable is used by the HttpClient service, therefore we import Observable, throwError, and RxJs Operators like map and catchError.
import { Observable, throwError } from 'rxjs'; import { map, catchError} from 'rxjs/operators';
In our example, the URL endpoint is hard-coded, but you may store the value in a config file and read it with the APP_INITIALIZER token.
baseURL: string = "https://api.github.com/";
Using Dependency Injection, we inject the HttpClient.
constructor(private http: HttpClient) { }
Finally, we use the httpclient's get method to send an HTTP Get request to GitHub.
The endpoint https://api.github.com/users/<username>?repos delivers a list of Repositories that belong to the user <userName>.
//Any Data Type getRepos(userName: string): Observable<any> { return this.http.get(this.baseURL + 'users/' + userName + '/repos') }
The observable is returned by httpclient.getmethod. As a result, in order to receive the data, we must subscribe to it.
Open the app.component.ts file and add the following code.
import { Component } from '@angular/core'; import { GitHubService } from './github.service'; import { repos } from './repos'; @Component({ selector: 'app-root', templateUrl: './app.component.html', }) export class AppComponent { userName: string = "jigneshpatel0748" repos: repos[]; loading: boolean = false; errorMessage; constructor(private githubService: GitHubService) { } public getRepos() { this.loading = true; this.errorMessage = ""; this.githubService.getRepos(this.userName) .subscribe( (response) => { //next() callback console.log('response received') this.repos = response; }, (error) => { //error() callback console.error('Request failed with error') this.errorMessage = error; this.loading = false; }, () => { //complete() callback console.error('Request completed') //This is actually not needed this.loading = false; }) } }
In our component class, we subscribe to the getRepos() method. The HTTP GET request to the back-end server is only sent when we subscribe to the observable.
this.githubService.getRepos(this.userName) .subscribe();
We can optionally pass the three callbacks when we subscribe to any observable. complete(), next(), and error().
The outcome of the observable is returned by the Next() callback. The list of repositories for the supplied user in this case.
(response) => { //next() callback console.log('response received') this.repos = response; }
An error can also be caused by the observable. It will call the error() callback with the error object as a parameter. After issuing the error signal, the observables come to a halt.
(error) => { //error() callback console.error('Request failed with error') this.errorMessage = error; this.loading = false; },
The complete() function will be called when the observable completes. This callback is unnecessary because the subscription ends when the data is received.
() => { //complete() callback console.log('Request completed') this.loading = false; })
Loading Indicator
Just before subscribing to the GETrequest, we set the variable loading=true. We set it to false when the observable completes or an error occurs. While we wait for the response, we can use this to show users a loading indicator.
Template
Now, add the following code under the app.component.html file.
<h1 class="heading"><strong>HTTP </strong>Demo</h1> <div class="form-group"> <label>GitHub User Name</label> <input class="form-control" name="userName" ngmodel="" type="text" username="" /> </div> <div class="form-group"> <button click="" getrepos="" type="button">Get Repos</button> </div> <div ngif="loading">loading...</div> <div class="alert alert-warning" ngif="errorMessage"> <strong>Warning!</strong> {{errorMessage | json}} </div> <table class="table"> <thead> <tr> <th>ID</th> <th>Name</th> <th>HTML Url</th> <th>description</th> </tr> </thead> <tbody> <tr ngfor="let repo of repos;"> <td>{{repo.id}}</td> <td>{{repo.name}}</td> <td>{{repo.html_url}}</td> <td>{{repo.description}}</td> </tr> </tbody> </table> <pre>{{repos | json}}</pre>
The template is very straightforward.
We begin by requesting the userName. To synchronize userName [(ngModel)]="userName" with the userName field in the component class, we use two-way data binding.
<div class="form-group"> <label>GitHub User Name</label> <input class="form-control" name="userName" ngmodel="" type="text" username="" /> </div>
The getRepos() method is an HTTP get method subscriber.
<div class="form-group"> <button click="" getrepos="" type="button">Get Repos</button> </div>
Until the observable delivers a response or an error, we show a loading message.
<div ngif="loading">loading...</div>
The error message will be displayed.
<div class="alert alert-warning" ngif="errorMessage"> <strong>Warning!</strong> {{errorMessage | json}} </div>
The response as it is received is shown in the last line.
<pre>{{repos | json}}</pre>
HTTP Get in Action
Now run the application and see if you can perform a successful GET Request.
Get Syntax
The HTTP get() method is demonstrated in the above code. The get() method's complete syntax is displayed below. It offers a second argument option that allows us to pass HTTP headers, arguments, and other options to influence how the get() method works.
get(url: string, options: { headers?: HttpHeaders | { [header: string]: string | string[]; }; params?: HttpParams | { [param: string]: string | string[]; }; observe?: "body|events|response|"; responseType: "arraybuffer|json|blob|text"; reportProgress?: boolean; withCredentials?: boolean;} ): Observable<>
headers: This is used to transmit the HTTP Headers with the request.
params: set URL parameters/query strings
observe: The return type is determined by this option.
responseType: The responseType value affects how the response will be parsed.
reportProgress: Whether or not this request should be made in such a way that progress events are exposed.
withCredentials: Is it necessary to send this request with outgoing credentials? (cookies).
observe
One of the following is returned by the GET method:
- Complete response
- body of the response
- events.
It returns the body by default, as an example in our sample app.
Complete Response
The code below will return the entire response, not just the body.
getReposRawResponse(userName: string): Observable<any> { return this.http.get(this.baseURL + 'users/' + userName + '/repos', { observe: 'response' }) }
The following is the whole response.
{ "headers": { "normalizedNames": {}, "lazyUpdate": null }, "status": 200, "statusText": "OK", "url": "https://api.github.com/users/jigneshpatel0748/repos", "ok": true, "type": 4, "body": [ { "id": 102269857, ****************** Removed for clarity ***** } ] }
events
You may also use the {observe: 'events', reportProgress: true} to listen to progress events. You can learn more about observing the response by reading this article.
getReposRawResponse(userName: string): Observable<any> { return this.http.get(this.baseURL + 'users/' + userName + '/repos', { observe: 'events', reportProgress: true }) }
Response Type
How the response is parsed is determined by the responseType. It can be an arraybuffer, a json blob, or a text. The response will be parsed as JSON by default.
Strongly typed response
We can also use a type instead of any, as seen below.
getReposTypedResponse(userName: string): Observable<repos> { return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos') }
String as Response Type
Instead of JSON, the API may return plain text. To ensure that the response is parsed as a string, use responsetype:'text'.
getReposTypedResponse(userName: string): Observable<repos> { return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos', { responsetype: 'text'}) }
Catching Errors
It's possible that the API will return an error. CatchError can be used to catch these errors. You can either handle the error or use the throw err method to return it to the component.
getReposCatchError(userName: string): Observable<repos> { return this.http.get<repos>(this.baseURL + 'usersY/' + userName + '/repos') .pipe( catchError((err) => { console.error(err); throw err; } ) ) }
Angular HTTP interceptor error handling has more information on error handling.
Transform the Response
Before sending the response to the component, you can edit or transform it using the map and filter RxJs Operators.
getReposMap(userName: string): Observable<repos> { return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos') .pipe( map((data) => { //You can perform some transformation here return data; }), catchError((err, caught) => { console.error(err); throw err; } ) ) }
URL Parameters
Using the HttpParams option, you can easily add URL parameters or query strings to the request. All you have to do now is create a new HttpParams class and populate it with the parameters given below.
//URL Parameter getReposUrlParameter(userName: string): Observable<repos> { const params = new HttpParams() .set('sort', "description") .set('page',"2"); return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos', { 'params': params }) .pipe( map((response) => { return response; }), catchError((err, caught) => { console.error(err); throw err; } ) ) }
The GET request is sent to the URL using the code above.
https://api.github.com/users/jigneshpatel0748/repos?sort=description&page=2
The code below also works.
getReposUrlParameter(userName: string): Observable<repos> { return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos?sort=description&page=2') .pipe( map((response) => { return response; }), catchError((err, caught) => { console.error(err); throw err; } ) ) }
HTTP Headers
You can also use the HttpHeaders option to add HTTP headers, as illustrated below. The HTTP Interceptor can be used to set the common headers.
//HTTP Headers getReposHeaders(userName: string): Observable<repos> { const params = new HttpParams() .set('sort', "description") .set('page',"2"); const headers = new HttpHeaders() .set('Content-Type', 'application/json') return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos', { 'params': params, 'headers': headers }) .pipe( map((response) => { return response; }), catchError((err, caught) => { console.error(err); throw err; } ) ) }
Send Cookies
With the withCredentials=true option, you can send cookies with every request, as demonstrated below. The HTTP Interceptor can be used to set withCredentials=true for all requests.
//With Credentials getReposWithCookies(userName: string): Observable<repos> { const params = new HttpParams() .set('sort', "description") .set('page',"2"); const headers = new HttpHeaders() .set('Content-Type', 'application/json') return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos', { 'params': params, 'headers': headers, withCredentials: true }) .pipe( map((response) => { return response; }), catchError((err, caught) => { console.error(err); throw err; } ) ) }
Conclusion
In this article using an example project, we learned how to use HTTP get in Angular. The HTTP post method will be covered in the next article.
I hope this article helps you and you will like it.👍
If you have any doubt or confusion then free to ask in the comment section.