HTTP POST In Angular
In this article, we will learn how to make an HTTP Post Request to a back-end server. In Angular, we use the HttpClient module. In Angular 4.3, the HttpClient Module was introduced. It's included in the @angular/common/http package. For this example, we'll make a fake backend server with JSON-server. We also demonstrate how to add HTTP headers, arguments, and query strings, as well as how to catch failures.
HTTP Post Example
Create a new Angular application using the following command:
ng new http-post
Import HttpClientModule
In app.module.ts, import the HttpClientModule and FormsModule. Add it to the imports array as well.
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { FormsModule } from '@angular/forms' import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule, FormsModule, ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Create Fake Backend
We used the publicly available GitHub API in the HTTP Get example. We'll need a backend server to receive the post request in this case.
A fake backend can be made in a variety of methods. You can use the JSON server or an in-memory web API. We'll be using the JSON Server in this article.
Using the npm command, install the JSON-server globally.
npm install -g json-server
Create a db.json file with some information. The data in the following example is made up of people's IDs and name fields.
{ "people": [ { "id": 1, "name": "Don Bradman" }, { "id": 2, "name": "Sachin Tendulkar" } ] }
Start the server using the following command:
json-server --watch db.json
On port 3000, the json-server starts and listens for requests.
Visit http://localhost:3000/ for further information. You should be able to see the home page at this point.
The people from the db.json are listed at http://localhost:3000/people. This URL can now be used with GET, POST, PUT, PATCH, DELETE, and OPTIONS.
Create a Model
Return to our app and add a Person model class under the person.ts.
export class Person { id:number name:string }
HTTP Post Service
Let us now establish a Service that is in charge of sending HTTP Requests. Copy the following code into a new file called api.service.ts.
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Person } from './person'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; @Injectable({providedIn:'root'}) export class ApiService { baseURL: string = "http://localhost:3000/"; constructor(private http: HttpClient) { } getPeople(): Observable<Person[]> { console.log('getPeople '+this.baseURL + 'people') return this.http.get<Person[]>(this.baseURL + 'people') } addPerson(person:Person): Observable<any> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); console.log(body) return this.http.post(this.baseURL + 'people', body,{'headers':headers}) } }
Our json-server server's endpoint is hard coded in our example, but you may store the value in a config file and read it with the APP_INITIALIZER token.
baseURL: string = "http://localhost:3000/";
Using Dependency Injection, we inject the HttpClient.
constructor(private http: HttpClient) { }
The getPeople() method retrieves a list of people using an HTTP GET request. For more information, see the Angular HTTP GET Example article.
getPeople(): Observable<Person[]> { console.log('getPeople '+this.baseURL + 'people') return this.http.get<Person[]>(this.baseURL + 'people') }
To add a new person to the backend, we use the addPerson function to send an HTTP POST request.
We need to set the 'content-type': 'application/json' in the HTTP header because we're transmitting JSON data. The person object is converted to a JSON string using JSON.stringify(person).
Finally, as seen below, we use the http.post() method with the URL, body, and headers.
addPerson(person:Person): Observable<any> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); console.log(body) return this.http.post(this.baseURL + 'people', body,{'headers':headers}) }
An observable is returned by the post() method. As a result, we must subscribe to it.
Example
We want the person's name in order to add them to our backend server. The ([(ngModel)]="person.name") two-way data binding keeps the person object in sync with the view.
Add the following code under the app.component.html file.
<h1>{{title}}</h1> <div> <div> <label>Name: </label> <input [(ngModel)]="person.name" /> </div> <div> <button (click)="addPerson()">Add</button> </div> </div> <table class='table'> <thead> <tr> <th>ID</th> <th>Name</th> </tr> </thead> <tbody> <tr *ngFor="let person of people;"> <td>{{person.id}}</td> <td>{{person.name}}</td> </tr> </tbody> </table>
We use the getPeople() method of our ApiService to make an HTTP get() request to get the list of people in the refreshPeople() method.
We subscribe to the apiService using the addPerson() method.
Under the addPerson() method, We use the refreshPeople() method to receive the updated list of individuals after the post request is complete.
Add the following code under the app.component.ts file.
import { Component, OnInit } from '@angular/core'; import { ApiService } from './api.service'; import { Person } from './person'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'httpGet Example'; people:Person[]; person = new Person(); constructor(private apiService:ApiService) {} ngOnInit() { this.refreshPeople() } refreshPeople() { this.apiService.getPeople() .subscribe(data => { console.log(data) this.people=data; }) } addPerson() { this.apiService.addPerson(this.person) .subscribe(data => { console.log(data) this.refreshPeople(); }) } }
Now, run the application and we are able to add a person and get an updated list on the screen looks like the below.
HTTP Post syntax
The above code shows how to use the HTTP post() method in a very basic way. The post() method's complete syntax is displayed below. URL and body are the first two arguments. The third argument allows us to pass HTTP headers, arguments, and other variables to customize how the post() method performs.
post(url: string, body: any, options: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body|events|response|"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType: "arraybuffer|json|blob|text"; withCredentials?: boolean; } ): Observable
headers: This is used to transmit the HTTP Headers with the request.
params: set URL parameters/query strings
observe: The type of return is determined by this option.
responseType: The responseType value affects how the response will be parsed.
reportProgress: Whether or not this request should be made in such a way that progress events are exposed.
withCredentials: Is it necessary to send this request with outgoing credentials? (cookies).
observe
One of the following is returned by the POST method:
- Complete response
- body of the response
- events.
It returns the body by default.
Complete Response
The code below will return the entire response, not just the body.
addPerson(person:Person): Observable<any> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); return this.http.post(this.baseURL + 'people', body,{'headers':headers , observe: 'response'}) }
events
You may also use the {observe: 'events', reportProgress: true} to listen to progress events. You can learn more about observing the response by reading this article.
return this.http.post(this.baseURL + 'people', body,{'headers':headers, observe: 'response',reportProgress: true})
Response Type
How the response is parsed is determined by the responseType. It can be an arraybuffer, a json blob, or text. The response will be parsed as JSON by default.
Strongly typed response
We can also use a type instead of any, as seen below.
addPerson(person:Person): Observable<Person> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); console.log(body) return this.http.post<Person>(this.baseURL + 'people', body,{'headers':headers}) }
String as Response Type
Instead of JSON, the API may return plain text. To ensure that the response is parsed as a string, use responsetype:'text'.
addPerson(person:Person): Observable<Person> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); return this.http.post<Person>(this.baseURL + 'people', body,{'headers':headers, responsetype: 'text'}) }
Catching Errors
It's possible that the API will return an error. CatchError can be used to catch these errors. You can either handle the error or use the throw err method to return it to the component.
addPerson(person:Person): Observable<Person> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); return this.http.post<Person>(this.baseURL + 'people', body,{'headers':headers}) .pipe( catchError((err) => { console.error(err); throw err; } ) }
Transform the Response
Before sending the response to the component, you can edit or transform it using the map and filter RxJs Operators.
addPerson(person:Person): Observable<Person> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); return this.http.post<Person>(this.baseURL + 'people', body,{'headers':headers}) .pipe( map((data) => { //You can perform some transformation here return data; }), catchError((err) => { console.error(err); throw err; } ) }
URL Parameters
Using the HttpParams option, you can easily add URL parameters or query strings to the request. All you have to do is create a new HttpParams class and populate it with the parameters shown below.
addPerson(person:Person): Observable<Person> { const headers = { 'content-type': 'application/json'} const params = new HttpParams() .set('para1', "value1") .set('para2',"value2"); const body=JSON.stringify(person); return this.http.post<Person>(this.baseURL + 'people', body,{'headers':headers, 'params': params}) }
The code above makes a GET call to the following:
URL: http://localhost:3000/people?para1=value1¶2=value2.
The code below also works.
addPerson(person:Person): Observable<Person> { const headers = { 'content-type': 'application/json'} const body=JSON.stringify(person); return this.http.post<Person>(this.baseURL + 'people?para1=value1¶2=value2', body,{'headers':headers)) }
HTTP Headers
You can also use the HttpHeaders option to add HTTP headers, as illustrated below. The HTTP Interceptor can be used to set the common headers. An HTTP header is already included in our example code.
Send Cookies
With the withCredentials=true option, you can send cookies with every request, as demonstrated below. The HTTP Interceptor can be used to set withCredentials=true for all requests.
return this.http.post<Person>(this.baseURL + 'people?para1=value1¶2=value2', body,{'headers':headers, withCredentials=true))
Conclusion
In this article. we learned how to use HTTP Post in Angular using the example app.
I hope this article helps you and you will like it.👍
If you have any doubt or confusion then free to ask in the comment section.