Angular 15 REST API By Example with HttpClient

In this article, we'll see how to use Angular HttpClient to send GET requests to REST API servers in your Angular 15 application. We'll also look at Angular services, RxJS Observables, models, and the async
pipe.
Front-end apps developed using frameworks like Angular connect with backend servers through REST APIs (based on the HTTP protocol) using either the XMLHttpRequest
interface or the fetch()
API.
The Angular HttpClient interface is based on the XMLHttpRequest
interface, which is also supported by older browsers.
Throughout this angular tutorial, we'll look at practical examples of how to utilize the HttpClient
class from the @angular/common/http
package to perform HTTP GET requests with the get()
method.
We'll also talk about:
- How to create a fake but fully functional REST API,
- How to create Angular services
- Subscribing to Observables,
- How to iterate through Observable data using the
async
pipe in templates.
Prerequisites
Before you can begin, there are a few prerequisites you must meet. You must have the following tools installed on your development system in order to work properly:
- Node.js and npm. You can install both from the official website.
- Angular CLI 15 (You can install it from npm using:
npm install -g @angular/cli
)
You'll also need to generate an Angular 15 project to complete the task.
If this is your first time working with the Angular CLI, just open your terminal and enter the following command to create a project:
$ ng new AngularHttpClientGetDemo
Setting up Angular 15 HttpClient
HttpClientModule
must be included in your main application's module as the very first step. Changes should be made to the src/app/app.module.ts
file as follows:
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
bootstrap: [AppComponent]
})
export class AppModule { }
All done, we are now prepared to use the HttpClient
in our angular 15 project.
Setting up a Fake REST API Server
A REST API server is required in order to demonstrate how to utilize the HttpClient
library. You may use an external API service, create a realistic Rest API server, or create a fake API using the json-server
library to accomplish the task. We'll choose the last approach in this example since it's less time-consuming than the first.
So, open up your terminal and begin by installing json-server
using the Node Package Manager (npm) as follows:
$ npm install -g json-server
Next define your data in a db.json
file:
{
"products": [
{
"id": 1,
"name": "Product001",
"cost": 10.0,
"quantity": 1000,
"locationId" : 1,
"familyId" : 1
},
{
"id": 2,
"name": "Product002",
"cost": 20.0,
"quantity": 2000,
"locationId" : 1,
"familyId" : 2
},
{
"id": 3,
"name": "Product003",
"cost": 30.0,
"quantity": 3000,
"locationId" : 3,
"familyId" : 2
},
{
"id": 4,
"name": "Product004",
"cost": 40.0,
"quantity": 4000,
"locationId" : 2,
"familyId" : 3
}
],
"locations":[
{
"id": 1,
"name": "Location001"
},
{
"id": 2,
"name": "Location002"
},
{
"id": 3,
"name": "Location003"
}
],
"families":[
{
"id": 1,
"name": "FM001"
},
{
"id": 2,
"name": "FM002"
},
{
"id": 3,
"name": "FM003"
}
],
"transactions":[
{
"id": 1,
"cost":11,
"quantity":10,
"productId":1
},
{
"id": 2,
"cost":12,
"quantity":100,
"productId":2
},
{
"id": 3,
"cost":15,
"quantity":101,
"productId":3
}
]
}
Following that, you may start a REST server by running the following command:
$ json-server --watch db.json
The HttpClient get()
Method
The HttpClient get()
function is intended to be used to send HTTP GET requests to the server. As an example, consider the following syntax:
get(url: string, options: {
headers?: HttpHeaders;
observe: 'response';
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<HttpResponse<Object>>;
It takes a REST API endpoint and an optional options
object and returns an Observable instance.
Now let's take a real world example. Let's presume you want to access the API endpoints we created above:
First you need to import HttpClient
in your component.
import { HttpClient } from '@angular/common/http';
Next you need to inject HttpClient
via the component's constructor
constructor(private httpClient: HttpClient){}
Next, add a method where you can call HttpClient.get(ENDPOINT_URL)
:
get_products(){
this.httpClient.get(this.baseUrl + '/products').subscribe((res)=>{
console.log(res);
});
}
When called, this method will make a GET request to the /products
endpoint then subscribe to the returned Observable. It
will then log the array of products to the console.
Now let's make a button to callthe get_products()
method:
<button (click)="get_products()">GET /products</button>
Now, If you want to show the products on the component template.
First, add a products
array:
private products = [];
Next change the get_products()
method as follows:
get_products(){
this.httpClient.get(this.baseUrl + '/products').subscribe((res : any[])=>{
console.log(res);
this.products = res;
});
}
We simply assing the returned products to the products
array.
Next, use the ngFor
directive in your component template to loop through the products
array:
<ul>
<li *ngFor="let product of products" >
-- id: {{product.id}}
-- name: {{product.name}}
-- cost: {{product.cost}}
-- quantity: {{product.quantity}}
</li>
</ul>
The async
pipe and Observables
In our example, We can access the data returned by the get()
method in two ways.
Subscribe to the returned Observable, i.e:
get_products(){
this.httpClient.get(this.baseUrl + '/products').subscribe((res : any[])=>{
console.log(res);
this.products = res;
});
}
Or use the async
pipe with the returned Observable and iterate directly over data in the template. Let's see how in more details.
First, you need to create an Observable using the following:
private productsObservable : Observable<any[]> ;
Next, call the get()
method and assign the result to productsObservable
:
this.productsObservable = this.httpClient.get(this.baseUrl + '/products');
Finally, in your template:
<li *ngFor="let product of productsObservable | async" >
-- id: {{product.id}}
-- name: {{product.name}}
-- cost: {{product.cost}}
-- quantity: {{product.quantity}}
</li>
We loop through the products using the Angular ngFor
directive.
Using Angular 15 Services
Using code that access data directly in your components is against the separation of concerns rule so let's refactor our code to use an Angular service which makes HTTP GET requests then returns the result back to our component(s).
Using Angular CLI, generate a new service:
$ ng generate service data
Next move the data access code to this service. Open the src/app/data.service.ts
file and update it accordingly:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class DataService {
baseUrl:string = "http://localhost:3000";
constructor(private httpClient : HttpClient) {}
get_products(){
return this.httpClient.get(this.baseUrl + '/products');
}
get_families(){
return this.httpClient.get(this.baseUrl + '/families');
}
get_locations(){
return this.httpClient.get(this.baseUrl + '/locations');
}
get_transactions(){
return this.httpClient.get(this.baseUrl + '/families');
}
}
Next, change the src/app/app.component.ts
file as follows:
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { DataService } from './data.service';
/* .... */
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private products = [];
private families = [];
private locations = [];
private transactions = [];
private productsObservable : Observable<any[]> ;
constructor(private dataService: DataService){
this.productsObservable = this.dataService.get_products();
this.dataService.get_families().subscribe((res : any[])=>{
this.families = res;
});
this.dataService.get_locations().subscribe((res : any[])=>{
console.log(res);
this.locations = res;
});
this.dataService.get_transactions().subscribe((res : any[])=>{
console.log(res);
this.transactions = res;
});
}
}
Instead of injecting HttpClient
directly in our component we inject our data service and call its methods to make GET requests to our REST API server.
Creating Angular Models
Now let's further refactor our code to use models for products, families, locations and transactions.
In the root of Angular project, create these models:
src/app/product.ts
export interface Product {
id: number;
name: string;
cost: number;
quantity: number;
locationId: number;
familyId: number;
}
src/app/family.ts
export interface Family {
id: number;
name: string;
}
src/app/location.ts
export interface Location {
id: number;
name: string;
constructor() { }
}
src/app/transaction.ts
export interface Transaction {
id: number;
cost: number;
productId: number;
quantity: number;
}
Next update your the src/app/app.component.ts
file to use the new models:
import { Product } from './product';
import { Family } from './family';
import { Location } from './location';
import { Transaction } from './transaction';
private products : Product[] = [];
private families : Family[] = [];
private locations : Location[] = [];
private transactions : Transaction[] = [];
private productsObservable : Observable<Product[]> ;
constructor(private dataService: DataService){
this.productsObservable = this.dataService.get_products();
this.dataService.get_families().subscribe((res : Family[])=>{
this.families = res;
});
this.dataService.get_locations().subscribe((res : Location[])=>{
this.locations = res;
});
this.dataService.get_transactions().subscribe((res : Transaction[])=>{
this.transactions = res;
});
}
You can find the complete source code of this demo in GitHub.
Conclusion
We demonstrated how to send GET requests to REST API servers from inside your Angular 15 application, and we looked at how to utilize HttpClient
, Angular services, RxJS Observables, models, and the async
pipe, among other things.
REST APIs are used by front-end applications written using frameworks such as Angular to communicate with backend servers. We can utilize either the XMLHttpRequest
interface or the fetch()
API to communicate with backend servers.
Since older browsers are also able to make use of the XMLHttpRequest
interface, it was used as the foundation of the Angular HttpClient.
We also discussed the following topics:
- How to develop a fake but completely working REST API.
- How to create Angular Services; in addition to subscribing to observables,
- How to iterate over Observable data in templates by utilizing the
async
pipe.
- Author: Ahmed Bouchefra Follow @ahmedbouchefra
-
Date: