Angular CRUD Example
July 02, 2019
This page will walk through Angular CRUD example using HttpClient
class. HttpClient
is an injectable class to make HTTP requests. CRUD operation is create, read, update and delete. HttpClient
class has methods to make HTTP calls such as HttpClient.post
will make HTTP POST request, HttpClient.put
will make HTTP put request, HttpClient.get
will make HTTP GET request and HttpClient.delete
will make HTTP DELETE request etc. All HttpClient
methods construct Observable
instance and make HTTP requests when they are subscribed.
On this page we will provide CRUD example using Angular in-memory web API. Now find the complete example step-by-step.
Contents
Technologies Used
Find the technologies being used in our example.1. Angular 8.0.3
2. TypeScript 3.4.3
3. Node.js 12.5.0
4. Angular CLI 8.0.6
5. Angular In-Memory Web API 0.8.0
Angular HttpClient
HttpClient
is smaller, easier and powerful library for making HTTP requests. HttpClient
is an injectable class. For any request it returns Observable
instance. It has following methods to perform HTTP requests.
post: Performs HTTP POST request.
get: Performs HTTP GET request.
put: Performs HTTP PUT request.
delete: Performs HTTP DELETE request.
patch: Performs HTTP PATCH request.
head: Performs HTTP HEAD request.
options: Performs HTTP OPTIONS request.
request: Performs any type of HTTP request.
jsonp: Performs HTTP JSONP request.
Observable.pipe
RxJSpipe
is used to combine functional operators into a chain. pipe
is an instance method of Observable
as well as a standalone RxJS function. pipe
can be used as Observable.pipe
or we can use standalone pipe
to combine functional operators. pipe
accepts operators as arguments such as filter
, map
, mergeScan
etc. with comma separated and execute them in a sequence they are passed in as arguments and finally returns Observable
instance. To get the result we need to subscribe
the final Observable
response. Find the sample code.
of(1, 2, 3, 4, 5, 6, 7).pipe( filter(n => n % 2 === 1), map(n => n + 10) ) .subscribe(result => console.log(result));
CRUD Operation using HttpClient
We will perform CREATE, READ, UPDATE and DELETE (CRUD) operation usingHttpClient
. We will perform
1. CREATE operation using
HttpClient.post
method.
2. READ operation using
HttpClient.get
method.
3. UPDATE operation using
HttpClient.put
method.
4. DELETE operation using
HttpClient.delete
method.
The print screen of our application for CRUD operation will be as follows.

HttpClient
step by step.
1. Import HttpClientModule
To useHttpClient
class, we need to import HttpClientModule
in application module. HttpClientModule
is from @angular/common/http
library.
app.module.ts
import { HttpClientModule } from '@angular/common/http'; @NgModule({ imports: [ --- HttpClientModule ], ------ }) export class AppModule { }
2. Inject HttpClient
HttpClient
is injectable and we can get its instance using constructor in a service class.
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class ArticleService { constructor(private http: HttpClient) { } ------ }
3. Create
We will perform create operation using AngularHttpClient.post()
method. HttpClient.post()
constructs an Observable
instance and performs HTTP POST operation when it is subscribed. Its syntax is as follows.
post(url, body, options): Observable<any>
url: This is the REST web service URL to create article.
body: This is the object that will be passed over HTTP request. In our example we will create an Angular class as
Article
and pass its instance to body
parameter.
options: We can pass options such as headers, parameters etc. This argument is optional.
HttpClient.post()
returns instance of Observable
which is a representation of any set of values over any amount of time.
Find the attributes that can be passed as options argument.
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.
Code
Find the code to create the article.
createArticle(article: Article): Observable<number> { let httpHeaders = new HttpHeaders({ 'Content-Type': 'application/json' }); return this.http.post<Article>(this.articleUrl + "/" + article.id, article, { headers: httpHeaders, observe: 'response' } ).pipe( map(res => res.status), catchError(this.handleError) ); }
Article
object to create an article and returning Observable
instance with status code.
4. Read
We will perform read operation using AngularHttpClient.get()
method. HttpClient.get()
constructs an Observable
instance and performs HTTP GET operation when it is subscribed. Find its syntax.
get(url, options): Observable<any>
options: We can pass options such as headers, parameters etc. This argument is optional.
Code
In our demo application we will fetch all articles as well as article by id. Find the code to fetch all articles.
getAllArticles(): Observable<Article[]> { return this.http.get<Article[]>(this.articleUrl).pipe( tap(articles => console.log("Number of articles: " + articles.length)), catchError(this.handleError) ); }
getArticleById(articleId: string): Observable<Article> { return this.http.get<Article>(this.articleUrl + "/" + articleId).pipe( tap(article => console.log(article.title + " " + article.category)), catchError(this.handleError) ); }
HttpClient.get()
returns Observable
instance and when it is subscribed, it will perform HTTP GET operation and returns response.
5. Update
We will perform update operation using AngularHttpClient.put()
method. HttpClient.put()
constructs an Observable
instance and performs HTTP PUT operation when it is subscribed. Find its syntax.
put(url, body, options): Observable<any>
url: This is the URL to update article.
body: This is the object that will be passed over HTTP request.
options: We can pass options such as headers, parameters etc. This argument is optional.
Code
Find the code to update the article.
updateArticle(article: Article): Observable<number> { let httpHeaders = new HttpHeaders({ 'Content-Type': 'application/json' }); return this.http.put<Article>(this.articleUrl + "/" + article.id, article, { headers: httpHeaders, observe: 'response' } ).pipe( map(res => res.status), catchError(this.handleError) ); }
Article
object to update for an article id and we are passing its instance to HttpClient.put()
method. The article will be updated for that article id.
6. Delete
We will perform delete operation using AngularHttpClient.delete()
method. HttpClient.delete()
constructs an Observable
instance and performs HTTP DELETE operation when it is subscribed. Find its syntax.
delete(url, options): Observable<any>
url: This is the URL to delete article.
options: We can pass options such as headers, parameters etc. This argument is optional.
Code
Find the code to delete article by id.
deleteArticleById(articleId: string): Observable<number> { return this.http.delete<number>(this.articleUrl + "/" + articleId).pipe( tap(status => console.log("status: " + status)), catchError(this.handleError) ); }
Install Angular In-Memory Web API
In our example we are using in-memory web API for CRUD operation. To use it in our angular application we need to follow below steps.Step-1: To install angular-in-memory-web-api, run below command from root folder of the project.
npm install angular-in-memory-web-api@0.8.0 --save
InMemoryDbService
interface. In our example we are creating an in-memory DB for articles.
test-data.ts
import { InMemoryDbService } from 'angular-in-memory-web-api'; export class TestData implements InMemoryDbService { createDb() { let articleDetails = [ { id: 101, title: 'Angular by Krishna', category: 'Angular' }, { id: 102, title: 'Core Java by Vishnu', category: 'Java' }, { id: 103, title: 'NgRx by Rama', category: 'Angular' } ]; return { articles: articleDetails }; } }
Step-3: Before using in-memory web API, we need to configure our above class in application module as following.
app.module.ts
import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; import { TestData } from './test-data'; @NgModule({ imports: [ ------ InMemoryWebApiModule.forRoot(TestData) ], ------ }) export class AppModule { }
1. GET /articles : Fetches all articles.
2. GET /articles/101 : Fetches article by id.
3. POST /articles : Create article.
4. PUT /articles : Update article by id.
5. DELETE /articles/101 : Delete article by id.
Complete Example
Find the project structure of our demo application.my-app | |--src | | | |--app | | | | | |--article.component.ts | | |--article.service.ts | | |--article.ts | | |--article.component.html | | |--article.component.css | | | | | |--app.component.ts | | |--app.module.ts | | | | | |--test-data.ts | | | |--assets | | | | | |--images | | | | | | | |--loading.gif | | | | | | |--main.ts | |--index.html | |--styles.css | |--node_modules |--package.json
article.ts
export class Article { id: number; title: string; category: string; }
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { map, catchError, tap } from 'rxjs/operators'; import { Article } from './article'; @Injectable({ providedIn: 'root' }) export class ArticleService { //URL for CRUD operations articleUrl = "/api/articles"; //Create constructor to get Http instance constructor(private http: HttpClient) { } //Fetch all articles getAllArticles(): Observable<Article[]> { return this.http.get<Article[]>(this.articleUrl).pipe( tap(articles => console.log("Number of articles: " + articles.length)), catchError(this.handleError) ); } //Create article createArticle(article: Article): Observable<number> { let httpHeaders = new HttpHeaders({ 'Content-Type': 'application/json' }); return this.http.post<Article>(this.articleUrl + "/" + article.id, article, { headers: httpHeaders, observe: 'response' } ).pipe( map(res => res.status), catchError(this.handleError) ); } //Fetch article by id getArticleById(articleId: string): Observable<Article> { return this.http.get<Article>(this.articleUrl + "/" + articleId).pipe( tap(article => console.log(article.title + " " + article.category)), catchError(this.handleError) ); } //Update article updateArticle(article: Article): Observable<number> { let httpHeaders = new HttpHeaders({ 'Content-Type': 'application/json' }); return this.http.put<Article>(this.articleUrl + "/" + article.id, article, { headers: httpHeaders, observe: 'response' } ).pipe( map(res => res.status), catchError(this.handleError) ); } //Delete article deleteArticleById(articleId: string): Observable<number> { return this.http.delete<number>(this.articleUrl + "/" + articleId).pipe( tap(status => console.log("status: " + status)), catchError(this.handleError) ); } private handleError(error: any) { console.error(error); return throwError(error); } }
import { Component, OnInit } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { ArticleService } from './article.service'; import { Article } from './article'; @Component({ selector: 'app-article', templateUrl: './article.component.html', styleUrls: ['./article.component.css'] }) export class ArticleComponent implements OnInit { //Component properties allArticles: Article[]; statusCode: number; requestProcessing = false; articleIdToUpdate = null; processValidation = false; //Create form articleForm = new FormGroup({ title: new FormControl('', Validators.required), category: new FormControl('', Validators.required) }); //Create constructor to get service instance constructor(private articleService: ArticleService) { } //Create ngOnInit() and and load articles ngOnInit(): void { this.getAllArticles(); } //Fetch all articles getAllArticles() { this.articleService.getAllArticles() .subscribe( data => this.allArticles = data, errorCode => this.statusCode = errorCode); } //Handle create and update article onArticleFormSubmit() { this.processValidation = true; if (this.articleForm.invalid) { return; //Validation failed, exit from method. } //Form is valid, now perform create or update this.preProcessConfigurations(); let article = this.articleForm.value; if (this.articleIdToUpdate === null) { //Generate article id then create article this.articleService.getAllArticles() .subscribe(articles => { //Generate article id (logic is for demo) let maxIndex = articles.length - 1; let articleWithMaxIndex = articles[maxIndex]; let articleId = articleWithMaxIndex.id + 1; article.id = articleId; //Create article this.articleService.createArticle(article) .subscribe(statusCode => { //Expecting success code 201 from server this.statusCode = statusCode; this.getAllArticles(); this.backToCreateArticle(); }, errorCode => this.statusCode = errorCode ); }); } else { //Handle update article article.id = this.articleIdToUpdate; this.articleService.updateArticle(article) .subscribe(statusCode => { //this.statusCode = statusCode; //Expecting success code 204 from server this.statusCode = 200; this.getAllArticles(); this.backToCreateArticle(); }, errorCode => this.statusCode = errorCode); } } //Load article by id to edit loadArticleToEdit(articleId: string) { this.preProcessConfigurations(); this.articleService.getArticleById(articleId) .subscribe(article => { this.articleIdToUpdate = article.id; this.articleForm.setValue({ title: article.title, category: article.category }); this.processValidation = true; this.requestProcessing = false; }, errorCode => this.statusCode = errorCode); } //Delete article deleteArticle(articleId: string) { this.preProcessConfigurations(); this.articleService.deleteArticleById(articleId) .subscribe(successCode => { //this.statusCode = successCode; //Expecting success code 204 from server this.statusCode = 204; this.getAllArticles(); this.backToCreateArticle(); }, errorCode => this.statusCode = errorCode); } //Perform preliminary processing configurations preProcessConfigurations() { this.statusCode = null; this.requestProcessing = true; } //Go back from update to create backToCreateArticle() { this.articleIdToUpdate = null; this.articleForm.reset(); this.processValidation = false; } }
<h1>Angular CRUD Example</h1> <h3 *ngIf="articleIdToUpdate; else create"> Update Article for Id: {{articleIdToUpdate}} </h3> <ng-template #create> <h3> Create New Article </h3> </ng-template> <div> <form [formGroup]="articleForm" (ngSubmit)="onArticleFormSubmit()"> <table> <tr> <td>Enter Title</td> <td> <input formControlName="title"> <label *ngIf="articleForm.get('title').invalid && processValidation" class="error"> Title is required. </label> </td> </tr> <tr> <td>Enter Category</td> <td> <input formControlName="category"> <label *ngIf="articleForm.get('category').invalid && processValidation" class="error"> Category is required. </label> </td> </tr> <tr> <td colspan="2"> <button *ngIf="!articleIdToUpdate">CREATE</button> <button *ngIf="articleIdToUpdate">UPDATE</button> <button (click)="backToCreateArticle()" *ngIf="articleIdToUpdate">Go Back</button> </td> </tr> </table> </form> <br/> <div *ngIf="statusCode; else processing"> <div *ngIf="statusCode === 201" class="success"> Article added successfully. </div> <div *ngIf="statusCode === 200" class="success"> Article updated successfully. </div> <div *ngIf="statusCode === 204" class="success"> Article deleted successfully. </div> <div *ngIf="statusCode === 500" class="error"> Internal Server Error. </div> </div> <ng-template #processing> <img *ngIf="requestProcessing" src="assets/images/loading.gif"> </ng-template> </div> <h3>Article Details</h3> <table> <tr> <th> Id</th> <th>Title</th> <th>Category</th> <th></th> <th></th> </tr> <tr *ngFor="let article of allArticles"> <td>{{article.id}}</td> <td>{{article.title}}</td> <td>{{article.category}}</td> <td> <button type="button" (click)="loadArticleToEdit(article.id)">Edit</button> </td> <td> <button type="button" (click)="deleteArticle(article.id)">Delete</button> </td> </tr> </table>
h1 { font-size: 2.0em; margin: 20px 0 0 0; font-weight: 400; } h3 { color: blue; } table { border-collapse: collapse; } table, th, td { border: 1px solid black; font-size:17px; } input { width: 225px; margin: 8px 0; background-color: #dfdfdf; font-size:17px; } button { background-color: #008CBA; color: white; } .error{ color: red; font-size: 20px; } .success{ color: green; font-size: 20px; }
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-article></app-article> ` }) export class AppComponent { }
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, HttpClientModule, ReactiveFormsModule, InMemoryWebApiModule.forRoot(TestData) ], declarations: [ AppComponent, ArticleComponent ], providers: [], bootstrap: [ AppComponent ] }) export class AppModule { }
Run Application
To run the application, find the steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your Angular CLI application. To install Angular CLI, find the link.
3. Install angular-in-memory-web-api@0.8.0
4. Run ng serve using command prompt.
5. Access the URL http://localhost:4200
References
Angular Doc: HttpClientHttpClient Example