Angular - HTTP DELETE Request



The HTTP DELETE

The HTTP standard verb DELETE can be used in the HTTP protocol to request the deletion of a specific resource (data) on the server. The purpose of the DELETE method is to ask the server to remove a particular piece of data.

In Angular, the HttpClient service class provides a delete() method to delete data on the server. Let's learn more about this method, including its signature, various options, real-time usage, etc.

Signature of the delete() Method

Following is the signature (different from syntax) of the HttpClient delete() method −

delete<T>(url: string, options?: Object): Observable<T>

Here,

  • URL − The URL to which the delete request is sent.
  • options − An object containing HTTP options such as headers, query parameters, etc.
  • Observable<T> − The return type, where 'T' represents the expected response type.

Options

Following is a list of the available options −

observe

The observe specifies which part of the response has to be observed during the server communication. Based on the observe option, either the full or part of the response will be returned as Observable. The possible values are body, events, and response.

body: Retrieves only the body content of the response from the HTTP request as Observable<R>, where R is based on the responseType option and the requested type (e.g., Expense) of data.

this.http.delete<Expense>(<url>, { 
'observe': 'body', 
'responseType' : 'json' 
})

Here,

  • JSON is the format used to interprets the response body
  • Expense is the requested type used to format the response body and returns as Observable<Expense>.

events: Retrieves the events fired in a response stream along with the corresponding response body as Observable<HttpEvent><R>>, where R is based on the responseType option and the requested type (e.g., Expense) of data.

this.http.delete<Expense>(<url>, { 
'observe': 'events', 
'responseType' : 'json' 
})

Here,

  • JSON is the format used to interprets the response body.
  • Expense is the requested type used to format the response body and returns Observable<HttpEvent<Expense>>.

response: It is used to retrieve the complete response from the HTTP request as Observable<HttpResponse<R>>, where R is based on the responseType option (which we will check in the next section) and the requested type (e.g., Expense) of data. The purpose of the HttpResponse class is to represent the complete HTTP response from the server.

this.http.delete<Expense>(<url>, { 
'observe': 'response', 
'responseType' : 'json' 
})

Here,

  • JSON is the format used to interprets the response body.
  • Expense is the requested type used to format the response body and returns Observable<HttpResponse<Expense>>.

responseType

The responseType is used to interpret the response body. It can have four possible values as shown below −

  • arraybuffer
  • blob
  • text
  • json

Let's understand the above options one by one:

arraybuffer: Interprets the response body as a generic raw binary data buffer and returns Observable. It can be used to stream audio/video content.

this.http.delete(<url>, { 
'observe': 'body', 
'responseType' : 'arraybuffer' 
})

blob: Interprets the response body as the binary format and returns Observable<blob>. It can be used to download large files.

this.http.delete(<url>, { 
'observe': 'body', 
'responseType' : 'blob'
})

text: Interprets the response body as plain text format and returns Observable<String>. It can be used to represent text-based data.

this.http.delete(<url>, { 
'observe': 'body', 
'responseType' : 'json'
})

JSON: Interprets the response body as JSON format and returns Observable<R>, where R is the requested type (e.g., Expense) of data. It can be used to represent the result in JSON format.

this.http.delete<Expense>(<url>, { 
'observe': 'body', 
'responseType' : 'json'
})

Based on the observe and responseType, HttpClient returns Observable with a different type variable. Let's check a few combinations of observe and responseType to better understand this concept.

  • observe => body and responseType => JSON

    Returns the Observable. R represents the type variable.

  • observe => response and responseType => JSON

    Returns the Observable<HttpResponse>. R represents the type variable and encodes response body.

  • observe => events and responseType => JSON

    Returns the Observable<HttpEvent>. R represents the type variable and encodes the response body.

  • observe => events and responseType => arraybuffer

    Returns the Observable<HttpEvent>. The response body is encoded as ArrayBuffer.

  • observe => response and responseType => blob

    Returns the Observable<HttpEvent>. The Response body is encoded as ArrayBuffer.

  • observe => response and responseType => text

    Returns the Observable<HttpResponse>. The Response body is encoded as ArrayBuffer.

We can combine observe and responseType to create many more combinations as necessary.

headers

Theheadersspecify the HTTP headers. It can include a standard HTTP header as a key/value pair or can encode the data in the HttpHeaders class. A sample header as a key/value pair is as follows:

{ 'Content-type': 'application/json' }

It specifies that the request content type is JSON. We can also use the HttpHeaders class provided by angular to create HTTP headers. A sample set of header information using HttpHeaders is as follows −

// create header using `HttpHeaders`
const headers = new HttpHeaders().set('content-type', 'application/json')
.set('Access-Control-Allow-Origin', '*');

this.http.delete<Expense>(<url>, { 
'observe': 'body', 
'responseType' : 'json', 
headers: headers
})

params

Theparamsrepresent the serialized request parameter in application/x-www-form-urlencoded format. It can include params as a key/value pair or can encode the data in the HttpParams class. A sample parameter as a key/value pair is as follows:

{ 'name': 'john' }

It specifies that the request param key is the name, and its value is john. We can also use the HttpParams class provided by angular to create parameters. A sample set of parameters using HttpParams is as follows −

// create parameters using `HttpParams`
const params = new HttpParams().set('name', 'john').set('age', 25)
.set('active', true;

this.http.delete<Expense>(<url>, { 
'observe': 'body', 
'responseType' : 'json', 
params: params 
})

context

Thecontextsends arbitrary values as key/value pairs with type safety and without key conflict. It is used as a source of information for interceptors acting as middle-ware between client and server. Angular provides a special class, HttpContext to encode the context information. A sample context is as follows:

// create a key using HttpContextToken
export const IS_AUTH_ENABLED = new HttpContextToken<boolean>(() => false);

// set data for the context
let authContext = new HttpContext().set(IS_AUTH_ENABLED, true)

this.http.request<Expense>('GET', <url>, { 
'observe': 'body', 
'responseType' : 'json', 
context: authContext 
})

Here,

  • HttpContextToken is used to create the key along with the value type.
  • IS_AUTH_ENABLED is the key, and its type is boolean.

reportProgress

The reportProgress is used to specify whether to send back the progress of the request (communication) from the server. It can be used to show the progress of large file uploads through web API:

this.http.delete<Expense>(<url>, { 
'observe': 'events', 
'responseType' : 'json', 
reportProgress: true 
})

withCredentials

The withCredentials is used to specify whether the request should be sent with outgoing credentials (cookies). It accepts the boolean value:

this.http.delete<Expense>(<url>, { 
'observe': 'body', 
'responseType' : 'json', 
withCredentials: true 
})

transferCache

ThetransferCache specifies whether the request should be cached. It accepts the boolean value or HttpTransferCacheOptions value. HttpTransferCacheOptions encode dynamic logic to filter requests to be cached based on a custom filter function and override default cache behavior:

this.http.delete<Expense>(<url>, { 
'observe': 'body', 
'responseType' : 'json', 
transferCache: true 
})

Working Example

To work out the HTTP client-server communication, we need to set up a web application and expose a set of web API. The web API can be requested from the client. Let us create a sample server application, Expense API App to provide CRUD REST API (mainlyDELETEmethod) for expenses −

Step 1: Go to your favorite workspace as shown below −

cd /go/to/your/favorite/workspace

Step 2: Create a new folder, expense-rest-api, and move into the folder −

mkdir expense-rest-api && cd expense-rest-api

Step 3: Create a new application using the init sub-command provided by the npm command as shown below −

npm init

Once you run the above command, it will ask a few questions and answer all of them with default answers.

Step 4: Install express and cors packages to create node-based web applications −

npm install express cors --save

Step 5: Install SQLite package to store the expenses in the SQLite-based database −

npm install sqlite3 --save

Step 6: Create a new file with the name sqlitedb.js, and add the below code to initialize the database with expense table and sample expense entries. An expense table will be used to store the expense item −

var sqlite3 = require('sqlite3').verbose()
const DBSOURCE = "expensedb.sqlite"

let db = new sqlite3.Database(DBSOURCE, (err) => {
   if (err) {
      console.error(err.message)
      throw err
   }else{
      console.log('Connected to the SQLite database.')
      db.run(`CREATE TABLE IF NOT EXISTS expense (
         id INTEGER PRIMARY KEY AUTOINCREMENT,
         item text, 
         amount real, 
         category text, 
         location text, 
         spendOn text, 
         createdOn text 
      )`,
         (err) => {
            if (err) {
               console.log(err);
            }else{
               var insert = 'INSERT INTO expense (item, amount, category, location, spendOn, createdOn) VALUES (?,?,?,?,?,?)'
         
               db.run(insert, ['Pizza', 10, 'Food', 'KFC', '2020-05-26 10:10', '2020-05-26 10:10'])
               db.run(insert, ['Pizza', 9, 'Food', 'Mcdonald', '2020-05-28 11:10', '2020-05-28 11:10'])
               db.run(insert, ['Pizza', 12, 'Food', 'Mcdonald', '2020-05-29 09:22', '2020-05-29 09:22'])
               db.run(insert, ['Pizza', 15, 'Food', 'KFC', '2020-06-06 16:18', '2020-06-06 16:18'])
               db.run(insert, ['Pizza', 14, 'Food', 'Mcdonald', '2020-06-01 18:14', '2020-05-01 18:14'])
            }
         }
      );  
   }
});

module.exports = db

Step 7: Open the index.js (if not found, create it manually) and place the below code −

var express = require("express")
var cors = require('cors')
var db = require("./sqlitedb.js")

var app = express()
app.use(cors());

var bodyParser = require("body-parser");
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

var HTTP_PORT = 8000
app.listen(HTTP_PORT, () => {
   console.log("Server running on port %PORT%".replace("%PORT%", HTTP_PORT))
});

app.get("/", (req, res, next) => {
   res.json({ "message": "Ok" })
});

app.get("/api/expense", (req, res, next) => {
   var sql = "select * from expense"
   var params = []
   db.all(sql, params, (err, rows) => {
   if (err) {
      res.status(400).json({ "error": err.message });
      return;
   }
   res.json(rows)
   });
   
});

app.get("/api/expense/:id", (req, res, next) => {
   var sql = "select * from expense where id = ?"
   var params = [req.params.id]
   db.get(sql, params, (err, row) => {
   if (err) {
      res.status(400).json({ "error": err.message });
      return;
   }
   res.json(row)
   });
});

app.use(function (req, res) {
   res.status(404);
});

Here, the code will create six below-mentioned REST API endpoints:

  • /endpoint returns an "OK" message to make sure the application is working fine.
  • /api/expense endpoint returns all expense items available in the database.
  • /api/expense/:id endpoint returns the expense entry based on the expense entry id.
  • /api/expense/:id endpoint with delete verb will delete the expense entry based on the expense entry id.

Step 8: Run the application using the below command −

node index.js

Step 9: To test the application, open your friendly browser (chrome) and go to http://localhost:8000/. It should return the below message if the application is working fine −

{ 
   "message": "Ok" 
}

Angular Sample Application

Let us create an angular application to delete an existing expense on the server using the HttpClient service class:

Step 1: Create a new angular application by running ng new command as shown below −

ng new my-http-app

Enable angular routing and CSS as shown below −

? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS

Step 2: Enable HTTP communication in the application by importing HttpClientModule in the component configuration file (app.component.ts) as per the latest version −

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet, HttpClientModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent {
  title = 'my-http-app';
}

Here,

  • Import the HttpClientModule from the @angular/common/http module.
  • Add the HttpClientModule into the imports array section of the @Component configuration.

Step 3: Create a new interface, Expense to represent our expense item −

interface Expense {
   id?: Number,
   item: String,
   amount: Number,
   category: String,
   location: String,
   spendOn: Date
}

export default Expense;

Here,

  • Anidis set as an optional property.

Step 4: Create a new component, ListExpenses to show the expense items from the server −

ng generate component ListExpenses

It will create the component as shown below −

CREATE src/app/list-expenses/list-expenses.component.css (0 bytes)
CREATE src/app/list-expenses/list-expenses.component.html (28 bytes)
CREATE src/app/list-expenses/list-expenses.component.spec.ts (602 bytes)
CREATE src/app/list-expenses/list-expenses.component.ts (229 bytes)

Step 5: Include our new component into the App root component view, app.component.html as shown below −

<app-list-expenses></app-list-expenses>
<router-outlet></router-outlet>

Step 6: Inject the HttpClient into the ListExpenses component through the constructor as shown below −

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
   selector: 'app-list-expenses',
   templateUrl: './list-expenses.component.html',
   styleUrls: ['./list-expenses.component.css']
})
export class ListExpensesComponent {

   constructor(private http: HttpClient) { }
}

Step 7: Implement the OnInit life cycle hook to request the server for expenses after the initialization of the ListExpenses component −

export class ListExpensesComponent implements OnInit{
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {
   }
}

Step 8: Create a local variable, expenses to hold our expenses from the server −

export class ListExpensesComponent implements OnInit{
   expenses: Expense[] = [];   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {   
   }
}

Step 9: Create a local variable, newexpense to hold the new expense created in the server −

export class ListExpensesComponent implements OnInit{
   expenses: Expense[] = [];
   newexpense: Expense | null = null;   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {   
   }
}

Step 10: Call the get method of this.http (HttpClient instance) object by passing the list expenses URL and options and getting the expense object from the server. Then, set the expenses into our local variable, expenses −

export class ListExpensesComponent implements OnInit {
   expenses: Expense[] = [];
   newexpense: Expense | null = null;   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {
      this.http.get<Expense[]>('http://localhost:8000/api/expense',
     {
	    'observe': 'body',
        'responseType': 'json'
     }).subscribe( data => {
         this.expenses = data as Expense[]
         console.log(this.expenses)
     })
   }
}

Here,

  • Sets the Expense[] as the type of the object returned by the server. The server will send the array of expense objects along with a new expense object in its body in the JSON format.
  • Subscribed to the request (this.http.get) object. Then parsed the subscribed data as an array of expense objects, and set it to a local expense variable (this.expenses).

Step 11: Add a new delete method and call thedelete()method of this.http (HttpClient instance) object by passing the delete URL −

export class ListExpensesComponent implements OnInit {
   expenses: Expense[] = [];
   newexpense: Expense | null = null;
   constructor(private http: HttpClient) { }   
   delete(id? : Number) : void {
      if (id) {
         this.http.delete<Expense>('http://localhost:8000/api/expense/' + id,{
            'observe': 'body',
            'responseType': 'json'
         }).subscribe( data => {
            console.log(data)
            this.http.get<Expense[]>('http://localhost:8000/api/expense',{
               'observe': 'body',
               'responseType': 'json'
            }).subscribe( data => {
                this.expenses = data as Expense[]
                console.log(this.expenses)
            })
         });
      }
   }   
   ngOnInit(): void {
      this.http.get<Expense[]>('http://localhost:8000/api/expense',{
         'observe': 'body',
         'responseType': 'json'
      })
      .subscribe( data => {
         this.expenses = data as Expense[];
         console.log(this.expenses);
      })
   
   }
}

Step 12: Next, get the expenses list object and render it in our component template page (list-expenses.component.html). Also, add an anchor tag for each expense and set the delete method by passing the corresponding expense ID −

<div><h3>Expenses</h3></div>
<ul>
   <li *ngFor="let expense of expenses">
      {{expense.item}} @ {{expense.location}} for {{expense.amount}} USD on {{expense.spendOn | date:'shortDate' }} <a href="delete(expense.id)">delete</a>
   </li>
</ul>

Here,

  • When the user clicks the delete link, it will call the delete expense endpoint and delete the expense from the server.

Step 13: The complete code of the ListExpensesComponent is as follows −

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpRequest, HttpResponse, HttpEvent, HttpParams } from '@angular/common/http';
import Expense from '../Expense';

@Component({
  selector: 'app-list-expenses',
  templateUrl: './list-expenses.component.html',
  styleUrls: ['./list-expenses.component.css']
})
export class ListExpensesComponent implements OnInit {
   expenses: Expense[] = [];
   newexpense: Expense | null = null;
   constructor(private http: HttpClient) { }
   ngOnInit(): void {
      var spend_date = new Date();
      spend_date.setDate(spend_date.getDate() - 1);
      this.newexpense = {
         'item': 'new item ' + Math.floor(Math.random() * 10),
         'amount': Math.floor(Math.random() * 100),
         'category': 'Food',
         'location': 'KFC',
         'spendOn': spend_date
   }
   this.http.delete<Expense>('http://localhost:8000/api/expense/1',
   this.newexpense,{
      'observe': 'body',
      'responseType': 'json'
   }).subscribe( data => {
         this.newexpense = data as Expense;
         console.log(data)
      });   
   this.http.get<Expense[]>('http://localhost:8000/api/expense',{
      'observe': 'body',
      'responseType': 'json'
   }).subscribe( data => {
        this.expenses = data as Expense[]
        console.log(this.expenses)
     });
   }
}

Step 14: Finally, run the application using the below command −

ng serve

Step 15: Open the browser and navigate to http://localhost:4200/ URL and check the output −

Here, the output shows our expenses as a list of items except item 1.

Conclusion

Angular provides an easy way to send data to the server through the HttpClient object.delete()is a specific method used to send data to the server. We will learn more HTTP methods to target other HTTP verbs in the upcoming chapters.

Multiple Choice Questions (MCQ's):

Here we have mentioned a few MCQs to test your knowledge on the current concept:

Answer : A

Explanation:

The DELETE method is used to request the removal of a specific resource on the server.

Q 2 − Which option in HttpClient.delete() allows you to specify query parameters in the request?

A − headers

B − context

C − params

D − responseType

Answer : C

Explanation:

The params option allows you to add query parameters to the request URL.

Answer : B

Explanation:

In the HttpClient.delete() method, the URL parameter represents the server address or endpoint to which the DELETE request will be sent in order to delete a specific resource.

Advertisements