Angular HttpClient (6/7/8/9/10): Consume REST API Example

by Didin J. on Aug 30, 2018 Angular HttpClient (6/7/8/9/10): Consume REST API Example

A comprehensive step by step Angular HttpClient (version 6/7/8/9/10) tutorial on consuming REST API from the remote server

A comprehensive tutorial of the Angular HttpClient (version 6/7/8/9/10) that use for consuming RESTAPI service from the remote server. Angular HttpClient is one of the fundamentals features of the Angular 6/7/8/9/10. We expect that you learn this tutorial by following a walkthrough of a working Angular application example. So, this will straight forward to the usage or implementation of Angular HttpClient.

Table of contents:

In this walkthrough tutorial, we will show you how to access external or remote RESTAPI service using this Angular HttpClient. For now, we will use existing Node.js, Express.js, and MongoDB RESTful API from our GitHub repository, or if you have PostgreSQL installed on your machine, you can get this REST API application. After this, the HttpClient feature will show you in an easy way and a little bit different from the original Angular docs.

Quotes: This example is compatible with Angular 6, 7, 8, 9, 10 because of no big changes on HttpClient, HttpHeaders, HttpErrorResponse, RxJS, Observable, and RxJS Operators. It just versions compatibility updates of their dependencies.

The following tools, frameworks, and modules are required to complete this Angular tutorial:

  1. Node.js (Recommended version)
  2. Angular
  3. Angular-CLI
  4. Node.js/Express MongoDB or PostgreSQL REST API
  5. Terminal (Mac/Linux) or Node Command Line (Windows)
  6. IDE or Text Editor

We assume that you have downloaded and installed Node.js environment. Now, let's check the above requirement by open the terminal or Node command line then go to your projects folder. Type this command to check the latest Node and NPM version.

node -v
v12.18.0
npm -v
6.14.5

That's our Node and NPM versions, before moving to the main steps of the Angular HttpClient tutorial, you will get the walkthrough in real practice in this silence Video tutorial. Not all, but it's practicable. Don't forget to like, share, comment, and subscribe to our Youtube channel.


Install/Update Angular CLI and Create Angular HttpClient Web Application

The Angular CLI is a tool to initialize, develop, scaffold, and maintain Angular applications. To install or upgrade the latest Angular CLI, type this command in the terminal or Node command line.

sudo npm install -g @angular/cli

If you use windows CMD, it might be not necessary to add `sudo`. Next, create a new Angular Web Application using this Angular CLI command.

ng new angular-httpclient

Next, go to the newly created Angular project folder.

cd ./angular-httpclient

If there are the questions to add routing, just press the "y" key and use "SCSS" as a stylesheet format.

? Would you like to add Angular routing? (y/N) Yes
? Which stylesheet format would you like to use? 
  CSS 
? SCSS   [ https://sass-lang.com/documentation/syntax#scss                ] 
  Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ] 
  Less   [ http://lesscss.org                                             ] 
  Stylus [ http://stylus-lang.com                                         ] 

Now, you run the new Angular web application using your own host and port.

ng serve --host 0.0.0.0 --port 8080

Open your browser then go to `localhost:8080` you will see this Angular page.

Angular HttpClient (6/7/8/9/10): Consume REST API Example - welcome page

Next, we will be working with IDE or Text Editor for this tutorial. To use Visual Studio Code, type this command under this Angular web app folder.

code .


Setup and Configure Angular HttpClient

In the created Angular web application, we will set up and configure Angular HttpClient. The modules already included with Angular, we just register the module for use within the Angular web application. Open and edit `src/app/app.module.ts` then add this import of Angular Common HTTP HttpClientModule.

import { HttpClientModule } from '@angular/common/http';

Add that module in `@NgModule` imports.

  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
  ],

That it's, now you can use the Angular HttpClient in your application.


Create Angular Service for consuming REST API using Angular HttpClient

We will put HttpClient access to the separate Angular service. For that, type this command to generate an Angular service after stopping the running Angular application by press `CTRL+C`.

ng g service rest

Next, open and edit `src/app/rest.service.ts` then add these HttpClient, HttpHeaders, HttpErrorResponse, Observable, RxJS, and RxJS Operators imports.

import { catchError } from 'rxjs/internal/operators';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { map } from 'rxjs/operators';

Inject the HttpClient module to the constructor params.

constructor(private http: HttpClient) { }

Declare the variable for RESTAPI endpoint before the @Injectable annotation.

const endpoint = 'http://localhost:3000/api/v1/';

Next, add a function to handle the error after at the bottom of the class body.

  private handleError(error: HttpErrorResponse): any {
    if (error.error instanceof ErrorEvent) {
      console.error('An error occurred:', error.error.message);
    } else {
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }
    return throwError(
      'Something bad happened; please try again later.');
  }

Non-Typed Response

For non-typed-response, add this function after the constructor to extract it.

  private extractData(res: Response): any {
    const body = res;
    return body || { };
  }

Add a function to GET products data from the REST API using HttpClient then subscribe to the response to RxJS Observable.

  getProducts(): Observable<any> {
    return this.http.get(endpoint + 'products').pipe(
      map(this.extractData),
      catchError(this.handleError)
    );
  }

Similar to the above function, this time GET product data by ID.

  getProduct(id: string): Observable<any> {
    return this.http.get(endpoint + 'products/' + id).pipe(
      map(this.extractData),
      catchError(this.handleError)
    );
  }

Typed Response

For typed response, add a new interface after the imports for mapping the response fields.

export interface Product {
  _id: string;
  prod_name: string;
  prod_desc: string;
  prod_price: number;
  updated_at: Date;
}

Add the functions of GET product list and product by ID.

  getProducts(): Observable<any> {
    return this.http.get<Product>(endpoint + 'products').pipe(
      catchError(this.handleError)
    );
  }

  getProduct(id: string): Observable<any> {
    return this.http.get<Product>(endpoint + 'products/' + id).pipe(
      catchError(this.handleError)
    );
  }

Add a function to POST new product data to the REST API using Angular HttpClient then subscribe to the response to RxJS Observable. This is an Angular POST example in the Angular service.

  addProduct(product: any): Observable<any> {
    return this.http.post(endpoint + 'products', product).pipe(
      catchError(this.handleError)
    );
  }

Add a function to PUT an updated product data by ID to the REST API using HttpClient then subscribe to the response to RxJS Observable.

  updateProduct(id: string, product: Product): Observable<any> {
    return this.http.put<Product>(endpoint + 'products/' + id, product).pipe(
      catchError(this.handleError)
    );
  }

Add a function to DELETE product by ID to the REST API using Angular HttpClient then subscribe to the response to RxJS Observable.

  deleteProduct(id: string): Observable<any> {
    return this.http.delete<Product>(endpoint + 'products/' + id).pipe(
      catchError(this.handleError)
    );
  }

The above functions show a complete RESTAPI CRUD operation such as GET, POST, PUT, and DELETE.  Simply as that, the main function of the Angular HttpClient. Next, we add the component for simple access to the Angular service.


Accessing Angular HttpClient Service from Component

Now, we have to access all RESTAPI Service call that using Angular HttpClient from the component. For that, add or generate all required components using these commands.

ng g component product
ng g component product-add
ng g component product-detail
ng g component product-edit

Open and edit `src/app/app.module.ts` then add an import of the Angular FormsModule.

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

Add that module to the @NgModule imports.

  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    FormsModule,
  ],

Next, open and edit `src/app/app-routing.module.ts` then add these imports of the generated components.

import { ProductComponent } from './product/product.component';
import { ProductDetailComponent } from './product-detail/product-detail.component';
import { ProductAddComponent } from './product-add/product-add.component';
import { ProductEditComponent } from './product-edit/product-edit.component';

Replace the routes constant with this.

const routes: Routes = [
  {
    path: 'products',
    component: ProductComponent,
    data: { title: 'Product List' }
  },
  {
    path: 'product-details/:id',
    component: ProductDetailComponent,
    data: { title: 'Product Details' }
  },
  {
    path: 'product-add',
    component: ProductAddComponent,
    data: { title: 'Product Add' }
  },
  {
    path: 'product-edit/:id',
    component: ProductEditComponent,
    data: { title: 'Product Edit' }
  },
  { path: '',
    redirectTo: '/products',
    pathMatch: 'full'
  }
];

Next, open and edit `src/app/app.component.html` then remove all tags except this tag.

<router-outlet></router-outlet>

Next, open and edit `src/app/product/product.component.ts` then replace all codes with this.

import { Component, OnInit } from '@angular/core';
import { RestService, Product } from '../rest.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.scss']
})
export class ProductComponent implements OnInit {

  products: Product[] = [];

  constructor(
    public rest: RestService,
    private router: Router) { }

  ngOnInit(): void {
    this.getProducts();
  }

  getProducts(): void {
    this.rest.getProducts().subscribe((resp: any) => {
      this.products = resp;
      console.log(this.products);
    });
  }

  add(): void {
    this.router.navigate(['/product-add']);
  }

  delete(id: string): void {
    this.rest.deleteProduct(id)
      .subscribe(() => {
          this.getProducts();
        }, (err) => {
          console.log(err);
        }
      );
  }

}

Open and edit `src/app/product/product.component.html` then replace all HTML tags with this Angular *ngFor iteration to iterate products list.

<h2>Product List</h2>

<div>
  <button (click)="add()">
    Add
  </button>
</div>

<ul class="products">
  <li *ngFor="let p of products; let i=index;">
    <a routerLink="/product-details/{{p._id}}">
      <span class="badge">{{i+1}}</span> {{p.prod_name}}
    </a>
    <button class="delete" title="delete product"
      (click)="delete(p._id)">x</button>
  </li>
</ul>

Open and edit `src/app/product/product.component.scss` then replace all CSS syntax with this.

/* Products Component's private CSS styles */
.products {
  margin: 0 0 2em 0;
  list-style-type: none;
  padding: 0;
  width: 15em;
}
.products li {
  position: relative;
  cursor: pointer;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}

.products li:hover {
  color: #607D8B;
  background-color: #DDD;
  left: .1em;
}

.products a {
  color: #888;
  text-decoration: none;
  position: relative;
  display: block;
  width: 250px;
}

.products a:hover {
  color:#607D8B;
}

.products .badge {
  display: inline-block;
  font-size: small;
  color: white;
  padding: 0.8em 0.7em 0 0.7em;
  background-color: #607D8B;
  line-height: 1em;
  position: relative;
  left: -1px;
  top: -4px;
  height: 1.8em;
  min-width: 16px;
  text-align: right;
  margin-right: .8em;
  border-radius: 4px 0 0 4px;
}

button {
  background-color: #eee;
  border: none;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
  cursor: hand;
  font-family: Arial;
}

button:hover {
  background-color: #cfd8dc;
}

button.delete {
  position: relative;
  left: 194px;
  top: -32px;
  background-color: gray !important;
  color: white;
}

And here the rest of the components codes.

`src/app/product-add/product-add.component.ts`

import { Component, OnInit, Input } from '@angular/core';
import { RestService } from '../rest.service';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-product-add',
  templateUrl: './product-add.component.html',
  styleUrls: ['./product-add.component.scss']
})
export class ProductAddComponent implements OnInit {

  @Input() productData = { prod_name: '', prod_desc: '', prod_price: 0 };

  constructor(public rest: RestService, private route: ActivatedRoute, private router: Router) { }

  ngOnInit(): void {
  }

  addProduct(): void {
    this.rest.addProduct(this.productData).subscribe((result) => {
      this.router.navigate(['/product-details/' + result._id]);
    }, (err) => {
      console.log(err);
    });
  }

}

`src/app/product-add/product-add.component.html`

<div>
  <h2>Product Add</h2>
  <div>
    <label>Product Name:
      <input [(ngModel)]="productData.prod_name" placeholder="Product Name"/>
    </label><br>
    <label>Product Desc:
      <input [(ngModel)]="productData.prod_desc" placeholder="Product Description"/>
    </label><br>
    <label>Product Price:
      <input [(ngModel)]="productData.prod_price" placeholder="Product Price"/>
    </label><br>
  </div>
  <button (click)="addProduct()">Save</button>
</div>

`src/app/product-detail/product-detail.component.ts`

import { Component, OnInit } from '@angular/core';
import { RestService, Product } from '../rest.service';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-product-detail',
  templateUrl: './product-detail.component.html',
  styleUrls: ['./product-detail.component.scss']
})
export class ProductDetailComponent implements OnInit {

  product: Product;

  constructor(public rest: RestService, private route: ActivatedRoute, private router: Router) { }

  ngOnInit(): void {
    this.rest.getProduct(this.route.snapshot.params.id).subscribe(
      (data: Product) => this.product = { ...data }
    );
  }

}

`src/app/product-detail/product-detail.component.html`

<div *ngIf="product" class="products">
  <h2>{{product.prod_name | uppercase}} Details</h2>
  <div><span>Description: </span>{{product.prod_desc}}</div>
  <div><span>Price: </span>{{product.prod_price}}</div>
  <div><span>Update Date: </span>{{product.updated_at | date}}</div>
  <div>
    <button routerLink="/product-edit/{{product._id}}">
      Edit
    </button>
  </div>
</div>

`src/app/product-edit/product-edit.component.ts`

import { Component, OnInit, Input } from '@angular/core';
import { RestService } from '../rest.service';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-product-edit',
  templateUrl: './product-edit.component.html',
  styleUrls: ['./product-edit.component.scss']
})
export class ProductEditComponent implements OnInit {

  @Input() productData: any = { prod_name: '', prod_desc: '', prod_price: 0 };

  constructor(public rest: RestService, private route: ActivatedRoute, private router: Router) { }

  ngOnInit(): void {
    this.rest.getProduct(this.route.snapshot.params.id).subscribe((data: {}) => {
      console.log(data);
      this.productData = data;
    });
  }

  updateProduct(): void {
    this.rest.updateProduct(this.route.snapshot.params.id, this.productData).subscribe((result) => {
      this.router.navigate(['/product-details/' + result._id]);
    }, (err) => {
      console.log(err);
    });
  }

}

`src/app/product-edit/product-edit.component.html`

<div>
  <h2>Product Edit</h2>
  <div>
    <label>Product Name:
      <input [(ngModel)]="productData.prod_name" placeholder="Product Name"/>
    </label><br>
    <label>Product Desc:
      <input [(ngModel)]="productData.prod_desc" placeholder="Product Description"/>
    </label><br>
    <label>Product Price:
      <input [(ngModel)]="productData.prod_price" placeholder="Product Price"/>
    </label><br>
  </div>
  <button (click)="updateProduct()">Update</button>
</div>


Run and Test Angular HttpClient Web Application

Before running the Angular HttpClient application, run the REST API server first. We use our Express.js/MongoDB RESTful application, so open the other tabs to run MongoDB server and Express.js server.

mongod
nodemon

Next, type this command in the current Terminal tabs to run the Angular 6 HttpClient application.

ng serve --open

You should enable CORS to make the RESTAPI server accessible from different server PORT. And here our Angular HttpClient Web application looks like.

Angular HttpClient (6/7/8/9/10): Consume REST API Example - edit
Angular HttpClient (6/7/8/9/10): Consume REST API Example - details
Angular HttpClient (6/7/8/9/10): Consume REST API Example - add
Angular HttpClient (6/7/8/9/10): Consume REST API Example - list

That it's, an example of Angular HttpClient RESTAPI service consumption. You can get the full source code on our GitHub and the latest update.

If you don’t want to waste your time design your own front-end or your budget to spend by hiring a web designer then Angular Templates is the best place to go. So, speed up your front-end web development with premium Angular templates. Choose your template for your front-end project here.

That just the basic. If you need more deep learning about MEAN Stack, Angular, and Node.js, you can take the following cheap course:

Thanks!

Loading…