Make HTTP Requests with Angular 16 HttpClient API

Last Updated on by in Angular

This step by step guide helps you ascertain the usage, implementation, on top of that, the benefits of HttpClient API in the Angular application. It also enables you to answer how to make HTTP (HTTP POST, GET, PUT, and DELETE) Requests.

Angular is a powerful and profound framework to makes the frontend job easy for frontend developers. It comes with tons of useful API which allow you to deal with almost any feature that falls in your task list.

It offers a facile way to Offset HTTP requests. This service is extant as an injectable class, with certain methods to execute HTTP requests.

Every request method has several signatures, and the return type varies rooted on the signature that is called (mainly the values of observing and responseType).

Today, you will understand the most basic and essential HttpClient API, which is used to make or send the HTTP requests (HTTP POST, GET, PUT, and DELETE) in an Angular application.

The worldwide web has drastically uplifted in recent times; since the SPA’s arrival (single page application), even browsers can handle the enigmatic JavaScript programs. Even more, modern applications can render data from remote HTTP servers.

XMLHttpRequest vs. Fetch API

When it comes to handling HTTP requests from Modern web browsers, they share the two most easy methods for getting and sending responses from third-party web servers.

XMLHttpRequest: XMLHttpRequest (XHR) objects are used to interact with servers. You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing. XMLHttpRequest is used heavily in AJAX programming.

The Fetch API: The Fetch API provides an interface for fetching resources (including across the network). It will seem familiar to anyone who has used XMLHttpRequest, but the new API provides a more powerful and flexible feature set.

HttpClient API Benefits

HttpClient is intuitive by the same token is a user-friendly API; it is innumerably beneficial:

  • Observable paradigm
  • Uncomplicated API Testing
  • Better Error Handling
  • Request and response interception
  • Powerful error handling mechanism
  • Request typed response objects

After the completion of this comprehensive tutorial, we reckon you will have the thorough understanding of:

  • What HttpClient is all about
  • How to import and use the HttpClientModule.
  • How to properly use HttpClient in Angular.
  • Creating REST API server using json-server package in Angular.
  • Making GET, POST, PUT, and DELETE requests in Angular with HttpClient API.

Formulate Angular Environment

First and foremost, download and establish Node on your development system:

Install Angular CLI, Before you create a new angular application:

npm install @angular/cli -g

If you have angular version < 11, then update to Angular 12:

ng update @angular/cli @angular/core

Now that you can create an angular application:

ng new angular-httpclient-example

Get inside the application root:

cd angular-httpclient-example

Install and register Bootstrap in Angular application:

npm install bootstrap

Add bootstrap CSS in angular.json file:

...
...
"styles": [
  "node_modules/bootstrap/dist/css/bootstrap.min.css",
  "src/styles.scss"
],
...
...

No Property Access From Index Signature

To resolve error:

Property ‘xxxName’ comes from an index signature, so it must be accessed with [‘xxxName’]

This setting makes sure profound consistency between accessing a field via the “dot” (obj.key) syntax, and “indexed” (obj["key"]) and the way which the property is declared in the type.

Without this flag, TypeScript will allow you to use the dot syntax to access fields which are not defined:

Make sure to set noPropertyAccessFromIndexSignature property to false under compilerOptions in tsconfig.json file:

"compilerOptions": {
// ...
// ...
   "noPropertyAccessFromIndexSignature": false,
// ...
// ...
}

Create Components

Angular components allow you to organize the code feature-wise, so you need to generate few components:

ng g c components/add-user

ng g c components/edit-user

ng g c components/users-list

Bring Routes & Navigation in Action

Routes are important to jump from one page to another, so create the following routes in the app-routing.module.ts file:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { AddUserComponent } from './components/add-user/add-user.component';
import { EditUserComponent } from './components/edit-user/edit-user.component';
import { UsersListComponent } from './components/users-list/users-list.component';

const routes: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'add' },
  { path: 'add', component: AddUserComponent },
  { path: 'edit/:id', component: EditUserComponent },
  { path: 'list', component: UsersListComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})

export class AppRoutingModule {}

Add HttpClientModule in Angular

We will explain to you how to import and inject HttpClientModule in the Angular application. Import the HttpClientModule from the ‘@angular/common/http’ library. Also, import and register and FormsModule in the same file:

Configures the dependency injector for HttpClient with supporting services for XSRF. Automatically imported by HttpClientModule.

Now, in this step, we will add the HttpClientModule also other modules and components in the app.module.ts file:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

import { FormsModule } from '@angular/forms';
import { AddUserComponent } from './components/add-user/add-user.component';
import { EditUserComponent } from './components/edit-user/edit-user.component';
import { UsersListComponent } from './components/users-list/users-list.component';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  declarations: [
    AppComponent,
    AddUserComponent,
    EditUserComponent,
    UsersListComponent,
  ],
  imports: [BrowserModule, HttpClientModule, FormsModule, AppRoutingModule],
  providers: [],
  bootstrap: [AppComponent],
})

export class AppModule {}

Next, install the json-server using the below command.

npm i json-server

Look for the database.json file, if it doesn’t exist create the file at the root path.

Make sure to add the given code into the file.

{
  "users": [
    {
    
    }
  ]
}

Head over to console, enter the command equally important hit enter:

json-server --watch database.json

Congratulations, you have just set up the local backend server for invoking HTTP requests.

Now, you can check the below endpoint on your browser:

http://localhost:3000/users

Setting Up Angular Service

Components cannot directly get or store the data, rather they are designed to display or assign data to a service.

What is more, we would like to show you how you can easily consume REST APIs with angular service. Generate CRUD service and define the User class within.

ng g s shared/crud

Add the following code in the app/shared/crud.service.ts file:

import { Injectable } from '@angular/core';

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

export class User {
  id?: string;
  name?: string;
  email?: string;
  phone?: number;
}

@Injectable({
  providedIn: 'root',
})

export class CrudService {
  endpoint = 'http://localhost:3000';

  constructor(private httpClient: HttpClient) {}

  httpHeader = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
    }),
  };

  getUsers(): Observable<User> {
    return this.httpClient
      .get<User>(this.endpoint + '/users')
      .pipe(retry(1), catchError(this.processError));
  }

  getSingleUser(id: any): Observable<User> {
    return this.httpClient
      .get<User>(this.endpoint + '/users/' + id)
      .pipe(retry(1), catchError(this.processError));
  }

  addUser(data: any): Observable<User> {
    return this.httpClient
      .post<User>(
        this.endpoint + '/users',
        JSON.stringify(data),
        this.httpHeader
      )
      .pipe(retry(1), catchError(this.processError));
  }

  updateUser(id: any, data: any): Observable<User> {
    return this.httpClient
      .put<User>(
        this.endpoint + '/users/' + id,
        JSON.stringify(data),
        this.httpHeader
      )
      .pipe(retry(1), catchError(this.processError));
  }

  deleteUser(id: any) {
    return this.httpClient
      .delete<User>(this.endpoint + '/users/' + id, this.httpHeader)
      .pipe(retry(1), catchError(this.processError));
  }

  processError(err: any) {
    let message = '';
    if (err.error instanceof ErrorEvent) {
      message = err.error.message;
    } else {
      message = `Error Code: ${err.status}\nMessage: ${err.message}`;
    }
    console.log(message);
    return throwError(() => {
      message;
    });
  }
}

You need to define the four functions on top of that; these methods will handle HTTP GET, POST, PUT and DELETE requests, respectively.

Not only but also, if any error comes, it will be processed by processError() function, it manifests server and client-side errors.

Handle HTTP GET, DELETE Request

You will learn to make an HTTP GET request in Angular using HttpClient API, to do so add the following code in the users-list.component.ts file:

import { Component, OnInit } from '@angular/core';
import { CrudService } from '../../shared/crud.service';

@Component({
  selector: 'app-users-list',
  templateUrl: './users-list.component.html',
  styleUrls: ['./users-list.component.scss'],
})

export class UsersListComponent implements OnInit {
  Users: any = [];

  constructor(public crudService: CrudService) {}

  ngOnInit() {
    this.fetchUsers();
  }

  fetchUsers() {
    return this.crudService.getUsers().subscribe((res: {}) => {
      this.Users = res;
    });
  }

  delete(id: any) {
    if (window.confirm('Really?')) {
      this.crudService.deleteUser(id).subscribe((res) => {
        this.fetchUsers();
      });
    }
  }
}

Add the following code in the users-list.component.html file:

<div class="container mt-5">
  <div class="d-flex flex-row-reverse bd-highlight">
    <button class="btn btn-primary" routerLink="/add">Add Empoyee</button>
  </div>

  <h2 class="mb-3 text-center">Users Collection</h2>

  <table class="table table-bordered">
    <thead>
      <tr>
        <th scope="col">#Id</th>
        <th scope="col">Name</th>
        <th scope="col">Email</th>
        <th scope="col">Phone</th>
        <th scope="col">Action</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let user of Users">
        <td>{{ user.id }}</td>
        <td>{{ user.name }}</td>
        <td>{{ user.email }}</td>
        <td>{{ user.phone }}</td>
        <td>
          <span class="edit btn-danger btn-sm btn" (click)="delete(user.id)"
            >Delete</span
          >
          &nbsp;
          <span
            class="edit btn-success btn-sm btn"
            routerLink="/edit/{{ user.id }}"
            >Edit</span
          >
        </td>
      </tr>
    </tbody>
  </table>
</div>

HTTP POST Request with HttpClient

This time you will learn to make HTTP POST request in Angular using HttpClient and angular service.

Add the following code in the add-users.component.ts file:

import { Component, OnInit, Input } from '@angular/core';
import { Router } from '@angular/router';
import { CrudService } from "../../shared/crud.service";

@Component({
  selector: 'app-add-user',
  templateUrl: './add-user.component.html',
  styleUrls: ['./add-user.component.scss']
})

export class AddUserComponent implements OnInit {

  @Input() userObj = { name: '', email: '', phone: 0 }

  constructor(
    public crudService: CrudService, 
    public router: Router
  ) { }

  ngOnInit(): void { }

  addUser(data: any) {
    this.crudService.addUser(this.userObj).subscribe((data: {}) => {
      this.router.navigate(['/list'])
    })
  }

}

Add the following code in the add-users.component.html file:

<div class="container" style="max-width: 500px;">
  <h3 class="mb-3 mt-5 text-center">Add User</h3>

  <div class="form-group">
    <input type="text" [(ngModel)]="userObj.name" class="form-control" placeholder="Name">
  </div>

  <div class="form-group">
    <input type="text" [(ngModel)]="userObj.email" class="form-control" placeholder="Email">
  </div>

  <div class="form-group">
    <input type="text" [(ngModel)]="userObj.phone" class="form-control" placeholder="Phone">
  </div>

  <div class="form-group">
    <button class="btn btn-success btn-lg btn-block" (click)="addUser(userObj)">Add User</button>
  </div>

</div>

Make HTTP PUT Request in Angular to Update Data

Lastly, you will see how to make HTTP PUT request with HttpClient to update the data into the server.

Add the following code in the edit-user.component.ts file:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { CrudService } from '../../shared/crud.service';

@Component({
  selector: 'app-edit-user',
  templateUrl: './edit-user.component.html',
  styleUrls: ['./edit-user.component.scss'],
})

export class EditUserComponent implements OnInit {
  id = this.actRoute.snapshot.params['id'];
  userObj: any = {};

  constructor(
    public crudService: CrudService,
    public actRoute: ActivatedRoute,
    public router: Router
  ) {}

  ngOnInit() {
    this.crudService.getSingleUser(this.id).subscribe((res: {}) => {
      this.userObj = res;
    });
  }

  updateUser(id: any, data: any) {
    if (window.confirm('Yes, please...')) {
      this.crudService.updateUser(this.id, data).subscribe((res) => {
        this.router.navigate(['/list']);
      });
    }
  }
}

Add the following code in the edit-user.component.html file:

<div class="container" style="max-width: 500px;">
    <h3 class="mb-3 mt-5 text-center">Update User</h3>
  
    <div class="form-group">
      <input type="text" [(ngModel)]="userObj.name" class="form-control" placeholder="Name">
    </div>
  
    <div class="form-group">
      <input type="text" [(ngModel)]="userObj.email" class="form-control" placeholder="Email">
    </div>
  
    <div class="form-group">
      <input type="text" [(ngModel)]="userObj.phone" class="form-control" placeholder="Phone">
    </div>
  
    <div class="form-group">
      <button class="btn btn-success btn-lg btn-block" (click)="updateUser(userObj.id, userObj)">Update User</button>
    </div>  
</div>

In the context of Angular, a router outlet is a directive that acts as a placeholder where the router renders the views for different routes.

Now, open the app.component.html file and replace all the code with the given single line of code.

<router-outlet></router-outlet>

We are now ready to view our app on the browser. Execute the below command to start the Angular app.

ng serve --open

Summary

We have completed the Angular 16 HttpClient tutorial. In this tutorial, we have seen the necessary methods to manage the HTTP requests, work with REST APIs, and set up a simple back-end server even more how to set up an Angular app with important APIs & services.