Angular HttpClient post

By Arvind Rai, January 26, 2024
This page will walk through Angular HttpClient.post() example. The HttpClient performs HTTP requests. The HttpClient.post() constructs an Observable with configured HTTP POST request and when the Observable instance is subscribed, POST request is executed on the server. In HttpClient.post() method, we need to pass URL, request body and optional HTTP options such as headers, response type etc. The HttpClient.post() returns Observable instance of given response type.
On this page we will see injecting HttpClient, creating request body and passing HTTP options. We will also look into error handling. For the demo we will use Angular In-Memory Web API to post data.

HttpClient.post

HttpClient is an Angular class to performs HTTP requests. HttpClient.post method performs POST request over HTTP. Find the HttpClient.post method signature from Angular Doc.
post(url: string, body: any | null, options: {
    headers?: HttpHeaders | {
        [header: string]: string | string[];
    };
    observe?: HttpObserve;
    params?: HttpParams | {
        [param: string]: string | string[];
    };
    reportProgress?: boolean;
    responseType?: 'arraybuffer' | 'blob' | 'json' | 'text';
    withCredentials?: boolean;
} = {}): Observable<any> 
HttpClient.post has following arguments.
1. url: Pass URL as string where we want to post data.
2. body: Pass data of any type as body to be posted.
3. options: We can pass options such as headers, parameters etc. This argument is optional.

The response type of HttpClient.post is RxJS Observable which represents values over any amount of time.

Find the attributes that can be passed as options argument in HttpClient.post request.
headers: Defines HttpHeaders for http POST request.
observe: Defines whether we want complete response or body only or events only.
params: Defines parameters in URL.
reportProgress: Defines whether we want progress report or not.
responseType: Defines response type such as arraybuffer, blob, json and text.
withCredentials: Defines whether we want to pass credentials or not.

HttpClientModule

To use HttpClient we need to import HttpClientModule in our application module. Find the code snippet.
import { HttpClientModule } from '@angular/common/http';
@NgModule({
  imports: [     
      HttpClientModule,
      ------	
  ],
  ------
})
export class AppModule { } 
Now we can inject HttpClient in injectable classes such as components and services.

Inject HttpClient and Post Request

We inject HttpClient using constructor into our components or services. HttpClient is imported from @angular/common/http library as following.
import { HttpClient } from '@angular/common/http'; 
Inject HttpClient using constructor as following.
constructor(private http: HttpClient) { 
} 
Now we are ready to call HttpClient methods using http instance. For example, find the code below.
createArticle(article: Article): Observable<Article> {
     return this.http.post<Article>(this.url, article);
} 
We need to provide generic return type to HttpClient.post method.

Subscribe to Post Method

All HttpClient methods return instance of Observable and they begin when we subscribe to them or use async pipe. So to begin our HttpClient.post method, we will call subscribe() method on it. Find the sample post method in our service.
createArticle(article: Article): Observable<Article> {
     return this.http.post<Article>(this.url, article);
} 
Find the code snippet from the component to subscribe our post method.
createArticle(article: Article) {
  this.articleService.createArticle(article).subscribe(
      article => {
        console.log(article);
      }
  );
} 

HttpClient.post Body

The body argument of HttpClient.post method is of any type. Find the sample example to post an object of Article type.
createArticle(article: Article): Observable<Article> {
     return this.http.post<Article>(this.url, article);
} 
We can also create body as following.
createArticle(): Observable<Article> {
  return this.http.post<Article>(this.url,
     {
	id: 100, 
	title: 'Java Functional Interface', 
	category: 'Java 8', 
	writer: 'Krishna'
     }
  );
} 

HttpClient.post with Headers

Angular provides HttpHeaders class to create request headers. HttpHeaders is immutable set of http headers with lazy parsing. It is imported as given below.
import { HttpHeaders } from '@angular/common/http'; 
We can instantiate HttpHeaders by passing headers into constructor or by using its set or append method. Find the sample code to instantiate HttpHeaders using constructor.
let httpHeaders = new HttpHeaders({
     'Content-Type' : 'application/json',
     'Cache-Control': 'no-cache'
}); 
Find the sample code to instantiate HttpHeaders using set method.
let httpHeaders = new HttpHeaders()
     .set('Content-Type', 'application/json')
     .set('Cache-Control', 'no-cache'); 
Now create http options.
let options = {
     headers: httpHeaders
}; 
Pass it to HttpClient.post method as third argument.
this.http.post<Article>(this.url, article, options); 
Our complete post request method will look as following.
createArticle(article: Article): Observable<Article> {
     let httpHeaders = new HttpHeaders({
	'Content-Type' : 'application/json',
	'Cache-Control': 'no-cache'
     });    
     let options = {
	headers: httpHeaders
     };        
     return this.http.post<Article>(this.url, article, options);
} 

HttpClient.post with observe Option

The HttpClient.post method can use observe property in http options to define whether we want complete response or body only or events only. We need to assign values for observe property as following.
observe : 'response' for complete response.
observe : 'body' for response with body.
observe : 'events' for response with events.

Suppose we want complete response for our request, then we will use observe property. Find the code snippet from the service.
postArticle(article: Article): Observable<HttpResponse<Article>> {
	let httpHeaders = new HttpHeaders({
		 'Content-Type' : 'application/json'
	});    
	return this.http.post<Article>(this.url, article,
		{
		  headers: httpHeaders,
		  observe: 'response'
		}
	);
} 
The HttpResponse is from @angular/common/http library. Now we will fetch body as well as headers of the response. Find the code snippet from the component.
saveArticle() {
 let article = {id: '2', title: 'Java Functional Interface',
          category: 'Java 8', writer: 'Krishna'};
 this.articleService.postArticle(article).subscribe(res => { 
	  let artcl: Article = res.body;
	  console.log(artcl.title);
	  console.log(res.headers.get('Content-Type'));		
	},
	err => {
	  console.log(err);
	}
 );
} 

HttpClient.post and Response Type

In HttpClient.post method we can provide responseType as http options and accordingly we need to provide return type to post method. The values of responseType are arraybuffer, blob, json and text.
Case-1: Default observe value is body and default responseType is json.
postArticle(article: Article): Observable<Article> {
  return this.http.post<Article>(this.url, article,
    {
	observe: 'body',
	responseType: 'json'
    }
  );
} 
If default observe value is body and default responseType is json, we can also write above method as following.
postArticle(article: Article): Observable<Article> {
    return this.http.post<Article>(this.url, article);
} 
Case-2: Suppose observe value is response and responseType is json. We will provide return type to HttpClient.post method as following.
postArticle(article: Article): Observable<HttpResponse<Article>> {
   return this.http.post<Article>(this.url, article,
     {
	observe: 'response',
	responseType: 'json'
     }
   );
} 

Error Handling

We can handle error while subscribing Observable instance returned from HttpClient.post. Find the sample code.
createArticle(article: Article) {
   this.articleService.createArticle(article).subscribe(
      article => {
        console.log(article);
      },
      err => {
        console.log(err);
      }
   );
} 
We can also use Angular HttpErrorResponse to handle error. It contains useful information regarding error. We need to import it from @angular/common/http library. Find the sample example.
saveArticle() {
     const article = {id: '2', title: 'Java Functional Interface',
          category: 'Java 8', writer: 'Krishna'};
     this.articleService.postArticle(article).subscribe(res => { 
          const artcl: Article = res.body;
          console.log(artcl?.title);
          console.log(res.headers.get('Content-Type'));		
        },
	(err: HttpErrorResponse) => {
          if (err.error instanceof Error) {
            //A client-side or network error occurred.				 
            console.log('An error occurred:', err.error.message);
          } else {
            //Backend returns unsuccessful response codes such as 404, 500 etc.				 
            console.log('Backend returned status code: ', err.status);
            console.log('Response body:', err.error);
          }
        }
     );
} 


Angular In-Memory Web API

Angular provides In-Memory Web API for dummy Web Service URL to test application. Find the steps to use Angular In-Memory Web API.
1. Open the command prompt and navigate to the directory where package.json resides and run following command.
npm i angular-in-memory-web-api@0.11.0 --save 
2. Create a class that will implement InMemoryDbService. Define createDb() method with dummy data.
test-data.ts
import { InMemoryDbService } from 'angular-in-memory-web-api';

export class TestData implements InMemoryDbService {
  createDb() {
    let articleDetails = [
      {id: 1, title: 'Angular Tutorials', category: 'Angular', writer: 'Mahesh'}
    ];
    return { articles: articleDetails };
  } 
} 
We will get following Web Service URL.
/api/articles 
3. Before using In-Memory Web API we need to import InMemoryWebApiModule in AppModule and configure TestData class as following.
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { TestData } from './test-data';

@NgModule({
  imports: [     
      ------
      InMemoryWebApiModule.forRoot(TestData)		
  ],
  ------
})
export class AppModule { } 
Find the link for more information on In-Memory Web API.

Complete Example

Find the project structure.
my-app
|
|--src
|   |
|   |--app 
|   |   |
|   |   |--article.ts
|   |   |--article.service.ts
|   |   |--article.component.ts
|   |   |--article.component.html
|   |   |
|   |   |--test-data.ts
|   |   |
|   |   |--app.component.ts
|   |   |--app.module.ts 
|   | 
|   |--main.ts
|   |--index.html
|   |--styles.css
|
|--node_modules
|--package.json 
Now find the complete code.
article.ts
export interface Article {
    id: string;
    title: string;
    category: string;
    writer: string;
} 
article.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Article } from './article';

@Injectable({
    providedIn: 'root'
})
export class ArticleService {
    url = "/api/articles";
    constructor(private http: HttpClient) { }

    createArticle(article: Article): Observable<Article> {
        let httpHeaders = new HttpHeaders()
            .set('Content-Type', 'application/json');
        let options = {
            headers: httpHeaders
        };
        return this.http.post<Article>(this.url, article, options);
    }
    postArticle(article: Article): Observable<HttpResponse<Article>> {
        let httpHeaders = new HttpHeaders({
            'Content-Type': 'application/json'
        });
        return this.http.post<Article>(this.url, article,
            {
                headers: httpHeaders,
                observe: 'response'
            }
        );
    }
    getAllArticles(): Observable<Article[]> {
        return this.http.get<Article[]>(this.url);
    }
} 
article.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { of } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { ArticleService } from './article.service';
import { Article } from './article';

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html'
})
export class ArticleComponent implements OnInit {
  dataSaved = false;
  articleForm = {} as FormGroup;
  allArticles$ = of([] as Article[]);
  constructor(private formBuilder: FormBuilder, private articleService: ArticleService) {
  }
  ngOnInit() {
    this.articleForm = this.formBuilder.group({
      title: ['', [Validators.required]],
      category: ['', [Validators.required]],
      writer: ['', [Validators.required]]
    });
    //this.loadAllArticles();
    this.saveArticle();
  }
  onFormSubmit() {
    this.dataSaved = false;
    let article = this.articleForm.value;
    this.articleService.getAllArticles().subscribe(articles => {
      let maxIndex = articles.length - 1;
      let maxIndexItem = articles[maxIndex];
      article.id = parseInt(maxIndexItem.id) + 1;
      this.createArticle(article);
    });
    this.articleForm.reset();
  }
  createArticle(article: Article) {
    this.articleService.createArticle(article).subscribe(
      article => {
        console.log(article);
        this.dataSaved = true;
        this.loadAllArticles();
      },
      err => {
        console.log(err);
      }
    );
  }
  loadAllArticles() {
    this.allArticles$ = this.articleService.getAllArticles();
  }
  get title() {
    return this.articleForm.get('title');
  }
  get category() {
    return this.articleForm.get('category');
  }
  get writer() {
    return this.articleForm.get('writer');
  }
  saveArticle() {
    const article = {
      id: '2', title: 'Java Functional Interface',
      category: 'Java 8', writer: 'Krishna'
    };
    this.articleService.postArticle(article).subscribe(res => {
      const artcl = res.body;
      console.log(artcl?.title);
      console.log(res.headers.get('Content-Type'));
      this.loadAllArticles();
    },
      (err: HttpErrorResponse) => {
        if (err.error instanceof Error) {
          //A client-side or network error occurred.				 
          console.log('An error occurred:', err.error.message);
        } else {
          //Backend returns unsuccessful response codes such as 404, 500 etc.				 
          console.log('Backend returned status code: ', err.status);
          console.log('Response body:', err.error);
        }
      }
    );
  }
} 
article.component.html
<h3>Create Article</h3>
<p *ngIf="dataSaved && articleForm.pristine" ngClass="success">
	Article created successfully.
</p>
<form [formGroup]="articleForm" (ngSubmit)="onFormSubmit()">
	<table>
		<tr>
			<td>Title: </td>
			<td>
				<input formControlName="title">
				<div *ngIf="title?.dirty && title?.errors" class="error">
					<div *ngIf="title?.errors?.required">
						Title required.
					</div>
				</div>
			</td>
		</tr>
		<tr>
			<td>Category: </td>
			<td>
				<input formControlName="category">
				<div *ngIf="category?.dirty && category?.errors" class="error">
					<div *ngIf="category?.errors?.required">
						Category required.
					</div>
				</div>
			</td>
		</tr>
		<tr>
			<td>Writer: </td>
			<td>
				<input formControlName="writer">
				<div *ngIf="writer?.dirty && writer?.errors" class="error">
					<div *ngIf="writer?.errors?.required">
						Writer required.
					</div>
				</div>
			</td>
		</tr>
		<tr>
			<td colspan="2">
				<button [disabled]="articleForm.invalid">Submit</button>
			</td>
		</tr>
	</table>
</form>
<h3>Article Details</h3>
<p *ngFor="let article of allArticles$ | async">
	{{article.id}} | {{article.title}} |
	{{article.category}} | {{article.writer}}
</p> 
app.component.ts
import { Component } from '@angular/core';

@Component({
   selector: 'app-root',
   template: `
	 <app-article></app-article>
    `
})
export class AppComponent {
} 
styles.css
table {
    border-collapse: collapse;
}
table, th, td {
    border: 1px solid black;
}
.error {
    color: red;
}
.success {
    color: green;
} 
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { ArticleComponent } from './article.component';

//For InMemory testing 
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { TestData } from './test-data';

@NgModule({
    imports: [
        BrowserModule,
        ReactiveFormsModule,
        HttpClientModule,
        InMemoryWebApiModule.forRoot(TestData)
    ],
    declarations: [
        AppComponent,
        ArticleComponent
    ],
    providers: [
    ],
    bootstrap: [
        AppComponent
    ]
})
export class AppModule { } 
Find the print-screen of the output.
Angular HttpClient post

References

Communicating with backend services
Angular Doc: HttpClient

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us