Sending POST PUT and DELETE Requests in Angular

Introduction

In modern web development, communicating with backend APIs is essential. Angular provides a powerful and easy-to-use HttpClient service that allows developers to perform all types of HTTP operations — including GET, POST, PUT, and DELETE.

While GET requests are used to retrieve data, the other three methods — POST, PUT, and DELETE — are responsible for creating, updating, and removing data from the server.
In this detailed post, we’ll explore each of these methods, their syntax, usage, handling responses, and best practices for writing maintainable and efficient API integrations.

Table of Contents

  1. Setting Up HttpClient in Angular
  2. Creating a Data Service for API Calls
  3. Understanding POST Requests
  4. Implementing POST Request in Angular
  5. Handling POST Response
  6. Example: Submitting a Form with POST
  7. Understanding PUT Requests
  8. Implementing PUT Request in Angular
  9. Handling PUT Response
  10. Example: Updating User Details
  11. Understanding DELETE Requests
  12. Implementing DELETE Request in Angular
  13. Handling DELETE Response
  14. Example: Deleting a Record
  15. Using Observables and Subscriptions
  16. Handling Errors with HttpClient
  17. Using HttpHeaders and Options
  18. Reusing API URLs with Environment Files
  19. Creating a Reusable Data Service
  20. Best Practices for POST, PUT, and DELETE
  21. Conclusion

1. Setting Up HttpClient in Angular

Before using any HTTP methods, the HttpClientModule must be imported in your Angular root module.

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

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  bootstrap: [AppComponent]
})
export class AppModule {}

Once imported, you can inject HttpClient into any service or component.


2. Creating a Data Service for API Calls

It’s a good practice to keep all API-related logic inside a dedicated Angular service.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/users';

  constructor(private http: HttpClient) {}
}

3. Understanding POST Requests

A POST request is used to send new data to the server — for example, creating a new user, product, or comment.
The server processes the request and usually returns the created object with an assigned ID or confirmation message.


4. Implementing POST Request in Angular

You can use the http.post() method to send data.

addUser(newUser: any): Observable<any> {
  return this.http.post(this.apiUrl, newUser);
}

In your component:

this.dataService.addUser({ name: 'John', email: '[email protected]' })
  .subscribe(response => {
console.log('User created:', response);
});

5. Handling POST Response

The response from the POST request is typically an object returned by the server.
It may include additional fields like an ID, timestamps, or status message.

You can also handle errors and completion:

this.dataService.addUser(newUser).subscribe({
  next: data => console.log('User Added:', data),
  error: err => console.error('Error:', err),
  complete: () => console.log('Request completed')
});

6. Example: Submitting a Form with POST

Imagine you have a user registration form.
When the form is submitted, the data is sent to the API using a POST request.

HTML Template:

<form (ngSubmit)="onSubmit()">
  <input type="text" [(ngModel)]="user.name" name="name" placeholder="Name">
  <input type="email" [(ngModel)]="user.email" name="email" placeholder="Email">
  <button type="submit">Submit</button>
</form>

Component Code:

user = { name: '', email: '' };

onSubmit() {
  this.dataService.addUser(this.user).subscribe(response => {
console.log('User created successfully:', response);
}); }

7. Understanding PUT Requests

A PUT request is used to update an existing record on the server.
While POST creates new data, PUT replaces or modifies existing data.

For example, updating a user’s information or editing a product’s price.


8. Implementing PUT Request in Angular

The http.put() method takes the resource URL and the updated object as parameters.

updateUser(id: number, updatedUser: any): Observable<any> {
  return this.http.put(${this.apiUrl}/${id}, updatedUser);
}

In your component:

this.dataService.updateUser(1, { name: 'Updated Name', email: '[email protected]' })
  .subscribe(response => {
console.log('User updated:', response);
});

9. Handling PUT Response

A successful PUT response may return the updated object or a status message.

You can handle responses like this:

this.dataService.updateUser(id, updatedData).subscribe({
  next: data => console.log('Updated Successfully:', data),
  error: err => console.error('Update Error:', err),
  complete: () => console.log('Update Complete')
});

10. Example: Updating User Details

Here’s an example where the user can edit details using a form.

HTML Template:

<form (ngSubmit)="onUpdate()">
  <input type="text" [(ngModel)]="user.name" name="name">
  <input type="email" [(ngModel)]="user.email" name="email">
  <button type="submit">Update</button>
</form>

Component Code:

user = { id: 1, name: 'John', email: '[email protected]' };

onUpdate() {
  this.dataService.updateUser(this.user.id, this.user)
.subscribe(result =&gt; console.log('User updated:', result));
}

11. Understanding DELETE Requests

A DELETE request removes an existing record from the server.
This is commonly used for actions like deleting a user, product, or comment.


12. Implementing DELETE Request in Angular

You can use the http.delete() method to remove data by ID.

deleteUser(id: number): Observable<any> {
  return this.http.delete(${this.apiUrl}/${id});
}

In your component:

this.dataService.deleteUser(1).subscribe(response => {
  console.log('User deleted:', response);
});

13. Handling DELETE Response

After deletion, the server usually returns a confirmation message or status code (e.g., 200 OK).

this.dataService.deleteUser(id).subscribe({
  next: data => console.log('Deleted:', data),
  error: err => console.error('Error:', err),
  complete: () => console.log('Delete Complete')
});

14. Example: Deleting a Record

HTML Template:

<ul>
  <li *ngFor="let user of users">
{{ user.name }}
&lt;button (click)="delete(user.id)"&gt;Delete&lt;/button&gt;
</li> </ul>

Component Code:

delete(id: number) {
  this.dataService.deleteUser(id).subscribe(() => {
this.users = this.users.filter(u =&gt; u.id !== id);
}); }

15. Using Observables and Subscriptions

Each HTTP method in Angular returns an Observable.
This means that data is fetched asynchronously, allowing for efficient updates and reactivity.

this.dataService.addUser(user).subscribe(response => {
  console.log('Async response:', response);
});

You can also use RxJS operators like map, catchError, or tap for more control.


16. Handling Errors with HttpClient

It’s crucial to handle errors gracefully.
You can use catchError from RxJS for error handling.

import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

addUser(user: any): Observable<any> {
  return this.http.post(this.apiUrl, user).pipe(
catchError(error =&gt; {
  console.error('Error:', error);
  return throwError(() =&gt; error);
})
); }

17. Using HttpHeaders and Options

You can send custom headers (like Content-Type or authentication tokens) with your HTTP requests.

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

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

this.http.post(this.apiUrl, user, { headers }).subscribe();

18. Reusing API URLs with Environment Files

Instead of hardcoding URLs, define them in environment files.

environment.ts:

export const environment = {
  production: false,
  apiUrl: 'https://jsonplaceholder.typicode.com/users'
};

Service File:

import { environment } from '../environments/environment';

private apiUrl = environment.apiUrl;

19. Creating a Reusable Data Service

You can build a generic service that handles all CRUD operations dynamically.

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  constructor(private http: HttpClient) {}

  get<T>(url: string): Observable<T> {
return this.http.get&lt;T&gt;(url);
} post<T>(url: string, data: any): Observable<T> {
return this.http.post&lt;T&gt;(url, data);
} put<T>(url: string, data: any): Observable<T> {
return this.http.put&lt;T&gt;(url, data);
} delete<T>(url: string): Observable<T> {
return this.http.delete&lt;T&gt;(url);
} }

Usage Example:

this.apiService.post('https://api.example.com/users', newUser)
  .subscribe(res => console.log(res));

20. Best Practices for POST, PUT, and DELETE Requests

  1. Use Services, not Components, for API Calls
    Keep your logic clean and reusable.
  2. Always Handle Errors
    Use RxJS catchError for better reliability.
  3. Use Environment Variables
    Never hardcode URLs or secrets.
  4. Use Strong Typing with Interfaces export interface User { id: number; name: string; email: string; }
  5. Unsubscribe to Avoid Memory Leaks
    Use takeUntil or async pipes where possible.
  6. Validate Data Before Sending
    Always ensure data is in the correct format before making a request.
  7. Use Interceptors for Tokens or Headers
    Interceptors can attach authentication tokens automatically.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *