The tutorial is an Angular 13 + MongoDB example with Node.js Express: CRUD. You can follow the introduction to create CRUD apps that use Angular 13 and Node js express rest API and MongoDB.
Following the below steps to create Angular 13 + Node JS MongoDB crud application:
- Step 1 – Create New Angular App
- Step 2 – Create Components in Angular
- Step 3 – Import Modules in app.module.ts
- Step 4 – Create CRUD Routes
- Step 5 – Build RESTful API using Node + Express js + MongoDB
- Step 6 – Create Angular Service for REST API Consumption
- Step 7 – Add code In app.component.html
- Step 8 – Create Operation
Step 1 – Create New Angular App
First of all, open your terminal and execute the following command on it to install an Angular app:
Firstly, open your terminal and execute the command to install an Angular app:
ng new my-new-app
Next, you need to execute the following command on the terminal to install angular material:
ng add @angular/material
Step 2 – Create Components in Angular
In this step, execute the following commands on the terminal to generate components in the angular application. Then, open your terminal and execute the below command:
ng g c components/add-book ng g c components/book-detail ng g c components/books-list
Step 3 – Import Modules in app.module.ts
In this step, visit the directory src/app and then open the file app.module.ts. After that you need to add the below code into the file:
... ... import { FormsModule, ReactiveFormsModule } from '@angular/forms' ; import { HttpClientModule } from '@angular/common/http' ; @NgModule({ declarations: [], imports: [ FormsModule, HttpClientModule, ReactiveFormsModule ], providers: [], bootstrap: [] }) export class AppModule { } |
Step 4 – Create CRUD Routes
In the step, you need to create routes with the help of Angular routes. You will make a consensus with components to enable the navigation in the CRUD application, then you need to add the following code in the app-routing.module.ts file.
import { NgModule } from '@angular/core' ; import { Routes, RouterModule } from '@angular/router' ; import { BooksListComponent } from './components/books-list/books-list.component' ; import { AddBookComponent } from './components/add-book/add-book.component' ; import { BookDetailComponent } from './components/book-detail/book-detail.component' ; const routes: Routes = [ { path: '' , pathMatch: 'full' , redirectTo: 'add-book' }, { path: 'books-list' , component: BooksListComponent }, { path: 'add-book' , component: AddBookComponent }, { path: 'edit-book/:id' , component: BookDetailComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } |
Step 5 – Build RESTful API using Node + Express js + MongoDB
In the step, we will introduce how to create RESTful API with Node and Express.js. We will learn to use MongoDB and how to handle data.
You need to execute the following command to invoke the REST API development with Node and Express.js:
mkdir node-rest-api && cd node-rest-api
Then you need to execute the command:
npm init -y
Next, you execute the below commands to install imperative npm packages that will help you to create REST APIs for your Angular CRUD system:
npm install express cors body-parser mongoose npm install nodemon --save-dev
In order to store the data flawlessly, you can use a reliable database of what else could be a better choice than MongoDB. So, execute the command to create a node-backend/database directory, and generate the db.js file where all the logic will be piled up for invoking the MongoDB connection.
mkdir database && cd database && touch db.js
Next, you need to add the following code in node-backend/database/db.js file.
module.exports = { db: 'mongodb://localhost:27017/db' }; |
Now, you have to create the Book model or schema, and create node-backend/model folder. Also, you need to create a Book.js file and add the below code into the file:
const mongoose = require( 'mongoose' ); const Schema = mongoose.Schema; let Book = new Schema({ name: { type: String }, price: { type: String }, description: { type: String } }, { collection: 'books' }) module.exports = mongoose.model( 'Book' , Book) |
Then, you need to define the REST API routes using Express js in the node project. Then you can create node-backend/routes folder, and create book.routes.js file. You need to add the below code into it:
const express = require( 'express' ); const app = express(); const bookRoute = express.Router(); let Book = require( '../model/Book' ); // Add Book bookRoute.route( '/add-book' ).post((req, res, next) => { Book.create(req.body, (error, data) => { if (error) { return next(error) } else { res.json(data) } }) }); // Get all Book bookRoute.route( '/' ).get((req, res) => { Book.find((error, data) => { if (error) { return next(error) } else { res.json(data) } }) }) // Get Book bookRoute.route( '/read-book/:id' ).get((req, res) => { Book.findById(req.params.id, (error, data) => { if (error) { return next(error) } else { res.json(data) } }) }) // Update Book bookRoute.route( '/update-book/:id' ).put((req, res, next) => { Book.findByIdAndUpdate(req.params.id, { $set: req.body }, (error, data) => { if (error) { return next(error); console.log(error) } else { res.json(data) console.log( 'Book updated successfully!' ) } }) }) // Delete Book bookRoute.route( '/delete-book/:id' ). delete ((req, res, next) => { Book.findByIdAndRemove(req.params.id, (error, data) => { if (error) { return next(error); } else { res.status(200).json({ msg: data }) } }) }) module.exports = bookRoute; |
Now, sum up all the code and conjugate it in one place so that you can run your backend and propel the CRUD app development forward.
Next, you create and add the following code in the index.js file:
let express = require( 'express' ), path = require( 'path' ), mongoose = require( 'mongoose' ), cors = require( 'cors' ), bodyParser = require( 'body-parser' ), mongoDb = require( './database/db' ); mongoose.Promise = global.Promise; mongoose.connect(mongoDb.db, { useNewUrlParser: true , useFindAndModify: false , useUnifiedTopology: true }).then(() => { console.log( 'Database sucessfully connected ' ) }, error => { console.log( 'Database error: ' + error) } ) const bookRoute = require( './routes/book.routes' ) const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cors()); // Static directory path app.use(express. static (path.join(__dirname, 'dist/angular-mean-crud-tutorial' ))); // API root app.use( '/api' , bookRoute) // PORT const port = process.env.PORT || 8000; app.listen(port, () => { console.log( 'Listening on port ' + port) }) // 404 Handler app.use((req, res, next) => { next(createError(404)); }); // Base Route app.get( '/' , (req, res) => { res.send( 'invaild endpoint' ); }); app.get( '*' , (req, res) => { res.sendFile(path.join(__dirname, 'dist/angular-mean-crud-tutorial/index.html' )); }); // error handler app.use( function (err, req, res, next) { console.error(err.message); if (!err.statusCode) err.statusCode = 500; res.status(err.statusCode).send(err.message); }); |
Step 6 – Create Angular Service for REST API Consumption
In the step, you need to visit app/service directory in Angular project and create Book.ts class within.
Then, you add the following code in app/service/Book.ts file:
export class Book { _id!: String; name!: String; price!: String; description!: String; } |
Then, you need to execute the command to create a crud service file:
ng g s service/crud
Then, you need to add the below code in app/service/crud.service.ts file:
import { Injectable } from '@angular/core' ; import { Book } from './Book' ; import { catchError, map } from 'rxjs/operators' ; import { Observable, throwError } from 'rxjs' ; import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http' ; @Injectable({ providedIn: 'root' }) export class CrudService { // Node/Express API // Http Header httpHeaders = new HttpHeaders().set( 'Content-Type' , 'application/json' ); constructor( private httpClient: HttpClient) { } // Add AddBook(data: Book): Observable<any> { let API_URL = `${ this .REST_API}/add-book`; return this .httpClient.post(API_URL, data) .pipe( catchError( this .handleError) ) } // Get all objects GetBooks() { return this .httpClient.get(`${ this .REST_API}`); } // Get single object GetBook(id:any): Observable<any> { let API_URL = `${ this .REST_API}/read-book/${id}`; return this .httpClient.get(API_URL, { headers: this .httpHeaders }) .pipe(map((res: any) => { return res || {} }), catchError( this .handleError) ) } // Update updateBook(id:any, data:any): Observable<any> { let API_URL = `${ this .REST_API}/update-book/${id}`; return this .httpClient.put(API_URL, data, { headers: this .httpHeaders }) .pipe( catchError( this .handleError) ) } // Delete deleteBook(id:any): Observable<any> { let API_URL = `${ this .REST_API}/ delete -book/${id}`; return this .httpClient. delete (API_URL, { headers: this .httpHeaders}).pipe( catchError( this .handleError) ) } // Error handleError(error: HttpErrorResponse) { let errorMessage = '' ; if (error.error instanceof ErrorEvent) { // Handle client error errorMessage = error.error.message; } else { // Handle server error errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`; } console.log(errorMessage); return throwError(errorMessage); } } |
Step 7 – Add code In app.component.html
In the step, you need to create HTML and for crud app in Angular. You need to visit src/app/app.component.html and update the below code into the HTML file:
< nav class = "navbar navbar-expand-lg navbar-light bg-light" > < a class = "navbar-brand" >Angular 13 CRUD Operations Demo</ a > < div id = "navbarNav" class = "collapse navbar-collapse" > < ul class = "navbar-nav ml-auto " > < li class = "nav-item" > < a class = "nav-link" routerLinkActive = "active" routerLink = "/books-list" >Show Books</ a > </ li > < li class = "nav-item" > < a class = "nav-link" routerLinkActive = "active" routerLink = "/add-book" >Add Books</ a > </ li > </ ul > </ div > </ nav > < router-outlet ></ router-outlet > |
Step 8 – Create Operation
After that, you can add the code in the add-book.component.ts file:
import { Component, OnInit, NgZone } from '@angular/core' ; import { Router } from '@angular/router' ; import { CrudService } from './../../service/crud.service' ; import { FormGroup, FormBuilder } from "@angular/forms" ; @Component({ selector: 'app-add-book' , templateUrl: './add-book.component.html' , styleUrls: [ './add-book.component.scss' ] }) export class AddBookComponent implements OnInit { bookForm: FormGroup; constructor( public formBuilder: FormBuilder, private router: Router, private ngZone: NgZone, private crudService: CrudService ) { this .bookForm = this .formBuilder.group({ name: [ '' ], price: [ '' ], description: [ '' ] }) } ngOnInit() { } onSubmit(): any { this .crudService.AddBook( this .bookForm.value) .subscribe(() => { console.log( 'Data added successfully!' ) this .ngZone.run(() => this .router.navigateByUrl( '/books-list' )) }, (err) => { console.log(err); }); } } |
Then, you need to add the following code in the add-book.component.html file:
< div class = "row justify-content-center mt-5" > < div class = "col-md-4" > < form [formGroup]="bookForm" (ngSubmit)="onSubmit()"> < div class = "form-group" > < label >Name</ label > < input class = "form-control" type = "text" formControlName = "name" required> </ div > < div class = "form-group" > < label >Price</ label > < input class = "form-control" type = "text" formControlName = "price" required> </ div > < div class = "form-group" > < label >Description</ label > < input class = "form-control" type = "text" formControlName = "description" required> </ div > < div class = "form-group" > < button class = "btn btn-primary btn-block" type = "submit" >Add Book</ button > </ div > </ form > </ div > </ div > |
Next, you add the below code in the books-list.component.ts file:
import { Component, OnInit } from '@angular/core' ; import { CrudService } from './../../service/crud.service' ; @Component({ selector: 'app-books-list' , templateUrl: './books-list.component.html' , styleUrls: [ './books-list.component.scss' ] }) export class BooksListComponent implements OnInit { Books:any = []; constructor( private crudService: CrudService) { } ngOnInit(): void { this .crudService.GetBooks().subscribe(res => { console.log(res) this .Books =res; }); } delete (id:any, i:any) { console.log(id); if (window.confirm( 'Do you want to go ahead?' )) { this .crudService.deleteBook(id).subscribe((res) => { this .Books.splice(i, 1); }) } } } |
Next, you add the below code in the books-list.component.html file:
< div class = "container" > < div class = "d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom" > < h2 class = "h2" >Books List</ h2 > </ div > < div class = "table-responsive" > < table class = "table table-bordered" > < thead > < tr > < th scope = "col" >Id</ th > < th scope = "col" >Name</ th > < th scope = "col" >Price</ th > < th scope = "col" >Description</ th > < th class = "text-center" scope = "col" >Action</ th > </ tr > </ thead > < tbody > < tr * ngFor = "let book of Books; let i = index" > < th scope = "row" >{{book._id}}</ th > < td >{{book.name}}</ td > < td >{{book.price}}</ td > < td >{{book.description}}</ td > < td class = "text-center" > < button class = "btn btn-sm btn-primary" routerLink = "/edit-book/{{book._id}}" >Edit</ button > < button class = "btn btn-sm btn-danger" (click)="delete(book._id, i)">Delete</ button > </ tr > </ tbody > </ table > </ div > </ div > |
Next, add the below code in the book-detail.component.ts file:
import { Component, OnInit, NgZone } from '@angular/core' ; import { Router, ActivatedRoute } from '@angular/router' ; import { CrudService } from './../../service/crud.service' ; import { FormGroup, FormBuilder } from "@angular/forms" ; @Component({ selector: 'app-book-detail' , templateUrl: './book-detail.component.html' , styleUrls: [ './book-detail.component.scss' ] }) export class BookDetailComponent implements OnInit { getId: any; updateForm: FormGroup; constructor( public formBuilder: FormBuilder, private router: Router, private ngZone: NgZone, private activatedRoute: ActivatedRoute, private crudService: CrudService ) { this .getId = this .activatedRoute.snapshot.paramMap.get( 'id' ); this .crudService.GetBook( this .getId).subscribe(res => { this .updateForm.setValue({ name: res[ 'name' ], price: res[ 'price' ], description: res[ 'description' ] }); }); this .updateForm = this .formBuilder.group({ name: [ '' ], price: [ '' ], description: [ '' ] }) } ngOnInit() { } onUpdate(): any { this .crudService.updateBook( this .getId, this .updateForm.value) .subscribe(() => { console.log( 'Data updated successfully!' ) this .ngZone.run(() => this .router.navigateByUrl( '/books-list' )) }, (err) => { console.log(err); }); } } |
Next, add the below code in the book-detail.component.html file:
< div class = "row justify-content-center mt-5" > < div class = "col-md-4" > < form [formGroup]="updateForm" (ngSubmit)="onUpdate()"> < div class = "form-group" > < label >Name</ label > < input class = "form-control" type = "text" formControlName = "name" required> </ div > < div class = "form-group" > < label >Price</ label > < input class = "form-control" type = "text" formControlName = "price" required> </ div > < div class = "form-group" > < label >Description</ label > < input class = "form-control" type = "text" formControlName = "description" required> </ div > < div class = "form-group" > < button class = "btn btn-primary btn-block" type = "submit" >Update</ button > </ div > </ form > </ div > </ div > |
For the topic of Angular 13 CRUD application using Node.js, Express.js, and MongoDB. In the tutorial, we introduce how to create a crud app in Angular 13 using Node js and Mongo DB with built REST API.