Angular 8/9/10 MEAN Stack CRUD with Angular Material 8 Last updated on August 4, 2020 by Digamber

Angular 8/9/10 MEAN Stack tutorial. In this tutorial, I’ll teach you how to build an Angular CRUD web application from scratch with MongoDB, Express js, Node js, and Angular Material UI library. Today I am going to share with you an. In this tutorial, I’ll teach you how to build an Angular CRUD web application from scratch with MongoDB, Express js, Node js, and Angular Material UI library. In this MEAN stack tutorial, you’ll learn to set up a MEAN stack project from scratch. I’ll be creating back-end and front-end for a real-world CRUD web application from scratch. For the demo purpose, I’ll create a students record management CRUD (create, read, update & delete) web application. In this CRUD app user will be able to perform the following tasks: Add student ID

Add student name

Add student email

Add section Angular Material dropdown

Add multiple subjects using Angular material input chips

Add student’s gender using Angular material radio buttons

Add student date of birth using Angular material datepicker Following topics will be covered in this tutorial: Angular Project Setup Setting up Node js

Setting up Angular CLI

Installing & setting up Angular project

Creating routes to navigate between components

Creating Angular service to manage CRUD operations

Consuming RESTful APIs using Angular Service Angular Material UI Library Setting up an Angular material ui library in a real-world Angular application.

Creating web application’s front-end using Angular material ui components like :- Angular material default theme, icons, buttons, navbar, date-picker, form, data tables and chip inputs. MEAN Stack Back-end Setup Set up MongoDB in Angular 8/9/10 MEAN stack app.

Setting up Express js server with Node js.

Creating RESTful APIs with Node js and Express js.

Workflow of MEAN Stack Angular Material Tutorial I’ll create application’s frontend in Angular 8/9/10 using Angular material 8 UI components and backend with Node js, Express js and MongoDb. To make it developer friendly I’ll create a separate project for frontend and backend. I will be building RESTful API using MEAN stack backend and will use those APIs with Angular service to consume the data. Following technologies, will be used throughout the tutorial. NPM v6.4.1

Node v10.15.3

RxJS V6.5.2

Angular v8.0.0

AngularCLI v8.0.0

MongoDB 4.0.6

MongoDB shell v4.0.6

Installing Node JS and Angular CLI Firstly, you need to have Node.js and Angular CLI installed in your system to work with Angular 8/9/10 Mean stack project. To install Node.js in your system, follow this tutorial How To Install Node JS on Your System? Node.js will help us to install the required dependencies for this Mean stack project. In the next step, we’ll be installing Angular CLI with the help of NPM. Now with the help of Angular CLI, we’ll install the new Mean stack project. npm install @angular/cli -g We’ve successfully installed Node.js and Angular CLI by now. Now we can use the ng command to generate new Angular project, components, services, routing or many more features of Angular.

Angular Project setup We are going to build a MEAN stack web app using Angular. In our MEAN stack web app, we’ll use the Angular framework to create the frontend of the app. Run the below command to generate a new angular project. ng new angular8-meanstack-angular-material Answer some Angular CLI questions: Head over to the newly created project folder. cd angular8-meanstack-angular-material In next step we’ll create three new components to manage Mean stack Angular CRUD app. Use Angular CLI to generate Angular components: ng g component components/add-student --module app ng g component components/edit-student --module app ng g component components/students-list --module app We are using --module app parameter because we have 2 module files in the app folder. Now with the –module app parameter We are telling Angular CLI that app.module.ts is our main app module file.

Setting up Routes to navigate between components. In this part of the tutorial we’ll create routes in our Mean stack Angular 8/9/10 CRUD app. Routes allow us to navigate between components in Angular app. import { NgModule } from '@angular/core' ; import { Routes , RouterModule } from '@angular/router' ; import { AddStudentComponent } from './components/add-student/add-student.component' ; import { EditStudentComponent } from './components/edit-student/edit-student.component' ; import { StudentsListComponent } from './components/students-list/students-list.component' ; const routes : Routes = [ { path : '' , pathMatch : 'full' , redirectTo : 'add-student' } , { path : 'add-student' , component : AddStudentComponent } , { path : 'edit-student/:id' , component : EditStudentComponent } , { path : 'students-list' , component : StudentsListComponent } ] ; @ NgModule ( { imports : [ RouterModule . forRoot ( routes ) ] , exports : [ RouterModule ] } ) export class AppRoutingModule { }

Setting up Angular Material UI Library in Angular project We’ll be using Angular Material UI library to build students record management system. I will help you to create a beautiful responsive layout with Angular material ui components. We’ll create Mean stack CRUD app with following Angular material UI components: Angular material default theme

Angular material date-picker

Angular material icons

Angular material buttons

Angular material navbar

Angular material form

Angular material data tables

Angular material chip inputs Run the following command to setup Angular material. ng add @angular/material Choose the Angular material theme as per your choice: ? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink ❯ Indigo/Pink [ Preview: https://material.angular.io?theme = indigo-pink ] Deep Purple/Amber [ Preview: https://material.angular.io?theme = deeppurple-amber ] Pink/Blue Grey [ Preview: https://material.angular.io?theme = pink-bluegrey ] Purple/Green [ Preview: https://material.angular.io?theme = purple-green ] Then it will ask for Hammer.js (Gesture recognition support) and Angular browser animation support. Select yes and hit enter. Set up HammerJS for gesture recognition? ( Y/n ) = Y ? Set up browser animations for Angular Material? ( Y/n ) = Y We’ve installed Angular material UI library in Mean stack project. Now we’ll create a separate material.module.ts file. In this file we’ll import the various Angular material service so that we can use it and manage centrally in our Angular 8/9/10 CRUD web app. In next step we’ll create a custom Angular material module, Create src > app > material.module.ts file and import the following Angular material UI components in this file like given below. import { NgModule } from '@angular/core' ; import { CommonModule } from '@angular/common' ; import { MatButtonModule , MatToolbarModule , MatIconModule , MatBadgeModule , MatSidenavModule , MatListModule , MatGridListModule , MatFormFieldModule , MatInputModule , MatSelectModule , MatRadioModule , MatDatepickerModule , MatNativeDateModule , MatChipsModule , MatTooltipModule , MatTableModule , MatPaginatorModule } from '@angular/material' ; @ NgModule ( { imports : [ CommonModule , MatButtonModule , MatToolbarModule , MatIconModule , MatSidenavModule , MatBadgeModule , MatListModule , MatGridListModule , MatFormFieldModule , MatInputModule , MatSelectModule , MatRadioModule , MatDatepickerModule , MatNativeDateModule , MatChipsModule , MatTooltipModule , MatTableModule , MatPaginatorModule ] , exports : [ MatButtonModule , MatToolbarModule , MatIconModule , MatSidenavModule , MatBadgeModule , MatListModule , MatGridListModule , MatInputModule , MatFormFieldModule , MatSelectModule , MatRadioModule , MatDatepickerModule , MatChipsModule , MatTooltipModule , MatTableModule , MatPaginatorModule ] , providers : [ MatDatepickerModule , ] } ) export class AngularMaterialModule { } Go to app.module.ts file and import the AngularMaterialModule. import { BrowserAnimationsModule } from '@angular/platform-browser/animations' ; import { AngularMaterialModule } from './material.module' ; import { NgModule , CUSTOM_ELEMENTS_SCHEMA } from '@angular/core' ; @ NgModule ( { declarations : [ ... ] , imports : [ BrowserAnimationsModule , AngularMaterialModule , ] , providers : [ ... ] , bootstrap : [ ... ] , schemas : [ CUSTOM_ELEMENTS_SCHEMA ] } ) export class AppModule { } Setup a basic layout with Angular Material Go to app.component.html file and include the following code. < mat-toolbar color = " primary " class = " header " > < div > Student Records </ div > < span class = " nav-tool-items " > < mat-icon (click) = " sidenav.toggle() " class = " hamburger " > menu </ mat-icon > </ span > </ mat-toolbar > < mat-sidenav-container > < mat-sidenav #sidenav [mode] = " isBiggerScreen() ? 'over' : 'side' " [(opened)] = " opened " [fixedInViewport] = " true " [fixedTopGap] > < mat-nav-list > < a mat-list-item routerLinkActive = " active " routerLink = " /add-student " > < mat-icon > add </ mat-icon > Add Student </ a > < a mat-list-item routerLinkActive = " active " routerLink = " /students-list " > < mat-icon > format_list_bulleted </ mat-icon > View Students </ a > </ mat-nav-list > </ mat-sidenav > < mat-sidenav-content > < router-outlet > </ router-outlet > </ mat-sidenav-content > </ mat-sidenav-container > Add the following code in app.component.ts file. import { Component , ViewChild , HostListener , OnInit } from '@angular/core' ; import { MatSidenav } from '@angular/material/sidenav' ; @ Component ( { selector : 'app-root' , templateUrl : './app.component.html' , styleUrls : [ './app.component.css' ] } ) export class AppComponent { opened = true ; @ ViewChild ( 'sidenav' ) sidenav : MatSidenav ; ngOnInit ( ) { console . log ( window . innerWidth ) if ( window . innerWidth < 768 ) { this . sidenav . fixedTopGap = 55 ; this . opened = false ; } else { this . sidenav . fixedTopGap = 55 ; this . opened = true ; } } @ HostListener ( 'window:resize' , [ '$event' ] ) onResize ( event ) { if ( event . target . innerWidth < 768 ) { this . sidenav . fixedTopGap = 55 ; this . opened = false ; } else { this . sidenav . fixedTopGap = 55 this . opened = true ; } } isBiggerScreen ( ) { const width = window . innerWidth || document . documentElement . clientWidth || document . body . clientWidth ; if ( width < 768 ) { return true ; } else { return false ; } } } To set up the style add the following code in styles.css file. html,body { height : 100% ; } body { margin : 0 ; font-family : 'Roboto' , sans-serif ; } .header { justify-content : space-between ; } .user-profile { margin-left : 15px ; } .mat-sidenav-container { height : 100% ; display : flex ; flex : 1 1 auto ; } .mat-nav-list .mat-list-item { font-size : 15px ; } .nav-tool-items { display : inline-block ; margin-right : 13px ; } .user-profile { margin-left : 15px ; cursor : pointer ; } .hamburger { visibility : hidden !important ; } .mat-sidenav,.mat-sidenav-content { padding : 15px ; } .mat-list-item.active { background : rgba ( 0 , 0 , 0 , .04 ) ; } .mat-sidenav-content { padding : 25px 40px 0 ; } .mat-sidenav { background-color : #F2F2F2 ; width : 250px ; } .header { position : sticky ; position : -webkit-sticky ; top : 0 ; z-index : 1000 ; } mat-sidenav mat-icon { margin-right : 12px ; } .hamburger { margin-top : 5px ; cursor : pointer ; } .mat-radio-button,.mat-radio-group { margin-right : 25px ; } .controlers-wrapper>* { width : 100% ; padding : 0 ; } .misc-bottom-padding { margin : 8px 0 10px ; } .misc-bottom-padding mat-label { margin-right : 15px ; } mat-radio-group mat-radio-button { margin-left : 5px ; } .button-wrapper button { margin-right : 5px ; } table.mat-table,table { width : 100% ; } .inner-wrapper { padding : 15px 0 130px ; width : 100% ; } .inner-wrapper mat-card { display : inline-block ; margin : 0 6% 0 0 ; vertical-align : top ; width : 44% ; } .full-wrapper { width : 100% ; } .multiple-items { position : relative ; } .multiple-items .tooltip-info { right : 0 ; top : 7px ; cursor : pointer ; color : #a1a7c7 ; position : absolute ; font-size : 20px ; } body .push-right { margin-right : 10px ; } .no-data { text-align : center ; padding-top : 30px ; color : #6c75a9 ; } .button-wrapper { margin : 20px 0 0 0 ; } @media ( max-width : 1024px ) { .inner-wrapper mat-card { width : 100% ; } .mat-sidenav-content { padding : 20px 20px 0 ; } .misc-bottom-padding mat-label { display : block ; padding-bottom : 10px ; } .mat-sidenav { width : 230px ; } .mat-nav-list .mat-list-item { font-size : 14px ; } } @media ( max-width : 767px ) { .nav-tool-items { margin-right : 0 ; } .hamburger { visibility : visible !important ; } } Your basic layout is ready ready with Angular material library, in next step we’ll set up backend using node js, express js and mongoDB.

Build Mean Stack Backend with MongoDB, Node JS and Express JS In this part of the tutorial, we are going to build a robust Mean stack backend using mongoDB, node js, and express js. Following topics will be covered in this part of the tutorial: Create a separate project for Mean stack backend.

Install required dependencies using NPM: body-parser, cors, express js, mongoose, and nodemon.

Set up MongoDB Database connection in Mean stack app to access MongoDB database using MongoDB Shell.

Define a data model with mongoose JS in Mean stack project.

Create RESTful APIs with Express js Routes in Mean Stack Project.

Configure Angular 8/9 Mean Stack backend Create a separate project for Mean stack backend. In order to set up a separate Mean stack backend create a folder by the name of backend in the Angular’s root directory. mkdir backend && cd backend You’ve created the backend folder and entered into the project. Next thing is to create a separate package.json for your Mean stack backend. npm init Install required dependencies using NPM: body-parser, cors, express js, mongoose, and nodemon. After that install the required dependencies for your Mean stack app. npm install --save express mongoose cors body-parser Then install nodemon package it will save us from restarting the server every-time we make the changes in our backend code. npm install nodemon --save-dev Your package.json file for Mean stack backend will look something like this. { "name" : "angular8-meanstack-backend" , "version" : "1.0.0" , "description" : "An angular 8 mean stack crud web app with angular material 8." , "main" : "index.js" , "scripts" : { "test" : "echo \"Error: no test specified\" && exit 1" } , "author" : "Digamber Rawat" , "license" : "ISC" , "dependencies" : { "body-parser" : "^1.19.0" , "cors" : "^2.8.5" , "express" : "^4.17.1" , "mongoose" : "^5.5.11" } , "devDependencies" : { "nodemon" : "^1.19.1" } } Set up MongoDB Database connection in Mean stack app to access MongoDB database using MongoDB Shell. To setup the MongoDB database connection within the Mean stack app, we need to create a folder by the name of database and create a file db.js there. Run the given below command. mkdir database && cd database && touch db.js Inside the backend > database > db.js file paste the following code. Here `angular8mean` is your mongoDB database name. module . exports = { db : 'mongodb://localhost:27017/angular8mean' } ; Define Student data model with mongoose JS in Mean stack app. We’ll create a model folder, inside the model folder we’ll create a Student Schema for students collection in MongoDB. Paste the below code in the model > Student.js file. const mongoose = require ( 'mongoose' ) ; const Schema = mongoose . Schema ; let Student = new Schema ( { student_name : { type : String } , student_email : { type : String } , section : { type : String } , subjects : { type : Array } , gender : { type : String } , dob : { type : Date } } , { collection : 'students' } ) module . exports = mongoose . model ( 'Student' , Student ) Create RESTful APIs with Express js Routes in Mean Stack Project. In this Angular 8/9/10 Mean stack tutorial we are going to create RESTful APIs using Express js and Node js. I will create a routes folder inside the backend folder and create a student.routes.js file. Enter the below command to create the routes folder and student.routes.js file. mkdir routes && cd routes && touch student.route.js We’ve created RESTful APIs using Express js and Student Model, now Go to student.route.js file and add the following code. const express = require ( 'express' ) ; const app = express ( ) ; const studentRoute = express . Router ( ) ; let Student = require ( '../model/Student' ) ; studentRoute . route ( '/add-student' ) . post ( ( req , res , next ) => { Student . create ( req . body , ( error , data ) => { if ( error ) { return next ( error ) } else { res . json ( data ) } } ) } ) ; studentRoute . route ( '/' ) . get ( ( req , res ) => { Student . find ( ( error , data ) => { if ( error ) { return next ( error ) } else { res . json ( data ) } } ) } ) studentRoute . route ( '/read-student/:id' ) . get ( ( req , res ) => { Student . findById ( req . params . id , ( error , data ) => { if ( error ) { return next ( error ) } else { res . json ( data ) } } ) } ) studentRoute . route ( '/update-student/:id' ) . put ( ( req , res , next ) => { Student . findByIdAndUpdate ( req . params . id , { $ set : req . body } , ( error , data ) => { if ( error ) { return next ( error ) ; console . log ( error ) } else { res . json ( data ) console . log ( 'Student successfully updated!' ) } } ) } ) studentRoute . route ( '/delete-student/:id' ) . delete ( ( req , res , next ) => { Student . findByIdAndRemove ( req . params . id , ( error , data ) => { if ( error ) { return next ( error ) ; } else { res . status ( 200 ) . json ( { msg : data } ) } } ) } ) module . exports = studentRoute ; Configure Mean Stack backend Now we’ll create app.js file in backend folder’s root. Run the below command to generate backend > app.js file. touch app . js Mange Backend settings in Mean stack Project. Now we are going to create app.js file this file will hold the core logic of our Mean stack project’s backend logic. This file will manage the following things. Setup port using express

Setup 404 error using express.js

Making mongoDB database connection

Serving static files using express js in Mean stack app

Handling errors using Express js in Angular Mean stack project let express = require ( 'express' ) , path = require ( 'path' ) , mongoose = require ( 'mongoose' ) , cors = require ( 'cors' ) , bodyParser = require ( 'body-parser' ) , dataBaseConfig = require ( './database/db' ) ; mongoose . Promise = global . Promise ; mongoose . connect ( dataBaseConfig . db , { useNewUrlParser : true , useFindAndModify : false } ) . then ( ( ) => { console . log ( 'Database connected sucessfully ' ) } , error => { console . log ( 'Could not connected to database : ' + error ) } ) const studentRoute = require ( './routes/student.route' ) const app = express ( ) ; app . use ( bodyParser . json ( ) ) ; app . use ( bodyParser . urlencoded ( { extended : false } ) ) ; app . use ( cors ( ) ) ; app . use ( express . static ( path . join ( __dirname , 'dist/angular8-meanstack-angular-material' ) ) ) ; app . use ( '/api' , studentRoute ) const port = process . env . PORT || 8000 ; app . listen ( port , ( ) => { console . log ( 'Connected to port ' + port ) } ) app . use ( ( req , res , next ) => { next ( createError ( 404 ) ) ; } ) ; app . get ( '/' , ( req , res ) => { res . send ( 'invaild endpoint' ) ; } ) ; app . get ( '*' , ( req , res ) => { res . sendFile ( path . join ( __dirname , 'dist/angular8-meanstack-angular-material/index.html' ) ) ; } ) ; app . use ( function ( err , req , res , next ) { console . error ( err . message ) ; if ( ! err . statusCode ) err . statusCode = 500 ; res . status ( err . statusCode ) . send ( err . message ) ; } ) ;

Build Angular 8/9/10 Service to Consume REST APIs To create Mean stack student records management system app. We need to create a service file where we’ll consume REST APIs to manage the student data. This service file will manage the Create, Read, Update and Delete operations. Configure Angular HttpClientModule: Import HttpClientModule service in app.module.ts file. import { HttpClientModule } from '@angular/common/http' ; @ NgModule ( { imports : [ HttpClientModule ] } ) Create & configure Student class: Enter the below command to create shared > student.ts file. export class Student { _id : String ; student_name : String ; student_email : String ; section : String ; subjects : Array < string > ; dob : Date ; gender : String ; } Create Angular 8/9/10 service to Consume REST APIs Enter the following command to create Angular service to manage CRUD operations in MEAN Stack web app. ng g s shared / api In the given below code we’ve consumed REST APIs using Angular service. Add the following code in your shared > api.service.ts file. import { Injectable } from '@angular/core' ; import { Student } from './student' ; import { Observable , throwError } from 'rxjs' ; import { catchError , map } from 'rxjs/operators' ; import { HttpClient , HttpHeaders , HttpErrorResponse } from '@angular/common/http' ; @ Injectable ( { providedIn : 'root' } ) export class ApiService { endpoint : string = 'http://localhost:8000/api' ; headers = new HttpHeaders ( ) . set ( 'Content-Type' , 'application/json' ) ; constructor ( private http : HttpClient ) { } AddStudent ( data : Student ) : Observable < any > { let API_URL = ` ${ this . endpoint } /add-student ` ; return this . http . post ( API_URL , data ) . pipe ( catchError ( this . errorMgmt ) ) } GetStudents ( ) { return this . http . get ( ` ${ this . endpoint } ` ) ; } GetStudent ( id ) : Observable < any > { let API_URL = ` ${ this . endpoint } /read-student/ ${ id } ` ; return this . http . get ( API_URL , { headers : this . headers } ) . pipe ( map ( ( res : Response ) => { return res || { } } ) , catchError ( this . errorMgmt ) ) } UpdateStudent ( id , data ) : Observable < any > { let API_URL = ` ${ this . endpoint } /update-student/ ${ id } ` ; return this . http . put ( API_URL , data , { headers : this . headers } ) . pipe ( catchError ( this . errorMgmt ) ) } DeleteStudent ( id ) : Observable < any > { var API_URL = ` ${ this . endpoint } /delete-student/ ${ id } ` ; return this . http . delete ( API_URL ) . pipe ( catchError ( this . errorMgmt ) ) } errorMgmt ( error : HttpErrorResponse ) { let errorMessage = '' ; if ( error . error instanceof ErrorEvent ) { errorMessage = error . error . message ; } else { errorMessage = ` Error Code: ${ error . status }

Message: ${ error . message } ` ; } console . log ( errorMessage ) ; return throwError ( errorMessage ) ; } } Go to app.module.ts file and import this API service like given below. import { ApiService } from './shared/api.service' ; @ NgModule ( { providers : [ ApiService ] } )

Add Student using MEAN Stack REST APIs with Angular Material In this part of the tutorial we will learn to add student in the MongoDB database. We’ll be using Angular Reactive form to add student in the database. Import ReactiveFormsModule API in App Module File In order to work with Reactive Forms we must import the ReactiveFormsModule API and FormsModule API in app.module.ts file. import { FormsModule , ReactiveFormsModule } from '@angular/forms' ; @ NgModule ( { imports : [ ReactiveFormsModule , FormsModule ] , } ) export class AppModule { } Go to add-student.component.ts file and include the given below code. import { Router } from '@angular/router' ; import { Component , OnInit , ViewChild , NgZone } from '@angular/core' ; import { COMMA , ENTER } from '@angular/cdk/keycodes' ; import { MatChipInputEvent } from '@angular/material' ; import { ApiService } from './../../shared/api.service' ; import { FormGroup , FormBuilder , Validators } from "@angular/forms" ; export interface Subject { name : string ; } @ Component ( { selector : 'app-add-student' , templateUrl : './add-student.component.html' , styleUrls : [ './add-student.component.css' ] } ) export class AddStudentComponent implements OnInit { visible = true ; selectable = true ; removable = true ; addOnBlur = true ; @ ViewChild ( 'chipList' ) chipList ; @ ViewChild ( 'resetStudentForm' ) myNgForm ; readonly separatorKeysCodes : number [ ] = [ ENTER , COMMA ] ; studentForm : FormGroup ; subjectArray : Subject [ ] = [ ] ; SectioinArray : any = [ 'A' , 'B' , 'C' , 'D' , 'E' ] ; ngOnInit ( ) { this . submitBookForm ( ) ; } constructor ( public fb : FormBuilder , private router : Router , private ngZone : NgZone , private studentApi : ApiService ) { } submitBookForm ( ) { this . studentForm = this . fb . group ( { student_name : [ '' , [ Validators . required ] ] , student_email : [ '' , [ Validators . required ] ] , section : [ '' , [ Validators . required ] ] , subjects : [ this . subjectArray ] , dob : [ '' , [ Validators . required ] ] , gender : [ 'Male' ] } ) } add ( event : MatChipInputEvent ) : void { const input = event . input ; const value = event . value ; if ( ( value || '' ) . trim ( ) && this . subjectArray . length < 5 ) { this . subjectArray . push ( { name : value . trim ( ) } ) } if ( input ) { input . value = '' ; } } remove ( subject : Subject ) : void { const index = this . subjectArray . indexOf ( subject ) ; if ( index >= 0 ) { this . subjectArray . splice ( index , 1 ) ; } } formatDate ( e ) { var convertDate = new Date ( e . target . value ) . toISOString ( ) . substring ( 0 , 10 ) ; this . studentForm . get ( 'dob' ) . setValue ( convertDate , { onlyself : true } ) } public handleError = ( controlName : string , errorName : string ) => { return this . studentForm . controls [ controlName ] . hasError ( errorName ) ; } submitStudentForm ( ) { if ( this . studentForm . valid ) { this . studentApi . AddStudent ( this . studentForm . value ) . subscribe ( res => { this . ngZone . run ( ( ) => this . router . navigateByUrl ( '/students-list' ) ) } ) ; } } } Then go to add-student.component.html file and add the following code. < ! -- Title group -- > < div class = "title-group" > < h1 class = "mat-h1" > Add Student < / h1 > < mat - divider fxFlex = "1 0" > < / mat - divider > < / div > < ! -- Form -- > < div class = "inner-wrapper" > < form [ formGroup ] = "studentForm" ( ngSubmit ) = "submitStudentForm()" #resetStudentForm = "ngForm" novalidate > < ! -- Left block -- > < mat - card > < div class = "controlers-wrapper" > < ! -- Name -- > < mat - form - field class = "example-full-width" > < input matInput placeholder = "Student name" formControlName = "student_name" > < mat - error * ngIf = "handleError('student_name', 'required')" > You must provide a < strong > student name < / strong > < / mat - error > < / mat - form - field > < ! -- Email -- > < mat - form - field class = "example-full-width" > < input matInput placeholder = "Student email" formControlName = "student_email" > < mat - error * ngIf = "handleError('student_email', 'required')" > You must provide a < strong > student email < / strong > < / mat - error > < / mat - form - field > < ! -- Section -- > < mat - form - field > < mat - label > Section < / mat - label > < mat - select [ ( value ) ] = "selected" formControlName = "section" > < mat - option [ value ] = "sectioinArray" * ngFor = "let sectioinArray of SectioinArray" > { { sectioinArray } } < / mat - option > < / mat - select > < mat - error * ngIf = "handleError('section', 'required')" > Section is required < / mat - error > < / mat - form - field > < / div > < / mat - card > < ! -- Right block -- > < mat - card > < div class = "controlers-wrapper" > < ! -- Add subjects -- > < mat - form - field class = "multiple-items" > < mat - chip - list #chipList > < mat - chip * ngFor = "let subjectArray of subjectArray" [ selectable ] = "selectable" [ removable ] = "removable" ( removed ) = "remove(subjectArray)" > { { subjectArray . name } } < mat - icon matChipRemove * ngIf = "removable" > cancel < / mat - icon > < / mat - chip > < input placeholder = "Add subject" [ matChipInputFor ] = "chipList" [ matChipInputSeparatorKeyCodes ] = "separatorKeysCodes" [ matChipInputAddOnBlur ] = "addOnBlur" ( matChipInputTokenEnd ) = "add($event)" > < / mat - chip - list > < i class = "material-icons tooltip-info" matTooltip = "Enter subject name and press enter to add subjects" > info < / i > < / mat - form - field > < ! -- Date of birth -- > < mat - form - field > < input matInput readonly [ matDatepicker ] = "picker" placeholder = "Date of birth" formControlName = "dob" ( dateChange ) = "formatDate($event)" > < mat - datepicker - toggle matSuffix [ for ] = "picker" > < / mat - datepicker - toggle > < mat - datepicker #picker > < / mat - datepicker > < mat - error * ngIf = "handleError('dob', 'required')" > Date of birth is required < / mat - error > < / mat - form - field > < ! -- Gender -- > < div class = "misc-bottom-padding" > < mat - label > Gender : < / mat - label > < mat - radio - group aria - label = "Select an option" formControlName = "gender" > < mat - radio - button value = "Male" > Male < / mat - radio - button > < mat - radio - button value = "Female" > Female < / mat - radio - button > < / mat - radio - group > < / div > < / div > < / mat - card > < ! -- Submit & Reset -- > < mat - card > < div class = "full-wrapper button-wrapper" > < div class = "button-wrapper" > < button mat - flat - button color = "warn" > Submit < / button > < / div > < / div > < / mat - card > < / form > < / div >

Show Students List and Delete Student Object Go to students-list.component.ts file and add the given below code. In this file, we’ll manage the following tasks. Implement the Angular material data tables and Pagination with Mean stack project.

Render Students List using Mean stack REST APIs

Delete Single Object using REST APIs in Mean stack app import { Student } from './../../shared/student' ; import { ApiService } from './../../shared/api.service' ; import { Component , ViewChild , OnInit } from '@angular/core' ; import { MatPaginator , MatTableDataSource } from '@angular/material' ; @ Component ( { selector : 'app-students-list' , templateUrl : './students-list.component.html' , styleUrls : [ './students-list.component.css' ] } ) export class StudentsListComponent implements OnInit { StudentData : any = [ ] ; dataSource : MatTableDataSource < Student > ; @ ViewChild ( MatPaginator ) paginator : MatPaginator ; displayedColumns : string [ ] = [ '_id' , 'student_name' , 'student_email' , 'section' , 'action' ] ; constructor ( private studentApi : ApiService ) { this . studentApi . GetStudents ( ) . subscribe ( data => { this . StudentData = data ; this . dataSource = new MatTableDataSource < Student > ( this . StudentData ) ; setTimeout ( ( ) => { this . dataSource . paginator = this . paginator ; } , 0 ) ; } ) } ngOnInit ( ) { } deleteStudent ( index : number , e ) { if ( window . confirm ( 'Are you sure' ) ) { const data = this . dataSource . data ; data . splice ( ( this . paginator . pageIndex * this . paginator . pageSize ) + index , 1 ) ; this . dataSource . data = data ; this . studentApi . DeleteStudent ( e . _id ) . subscribe ( ) } } } Now, go to students-list.component.html file and include the following code. < div class = " title-group " > < h1 class = " mat-h1 " > Students List </ h1 > < mat-divider fxFlex = " 1 0 " > </ mat-divider > </ div > < p *ngIf = " StudentData.length <= 0 " class = " no-data " > There is no student added yet! </ p > < div class = " container " *ngIf = " StudentData.length > 0 " > < div class = " mat-elevation-z8 " > < table mat-table [dataSource] = " dataSource " > < ng-container matColumnDef = " _id " > < th mat-header-cell *matHeaderCellDef > Student ID </ th > < td mat-cell *matCellDef = " let element " > {{element._id}} </ td > </ ng-container > < ng-container matColumnDef = " student_name " > < th mat-header-cell *matHeaderCellDef > Student Name </ th > < td mat-cell *matCellDef = " let element " > {{element.student_name}} </ td > </ ng-container > < ng-container matColumnDef = " student_email " > < th mat-header-cell *matHeaderCellDef > Email </ th > < td mat-cell *matCellDef = " let element " > {{element.student_email}} </ td > </ ng-container > < ng-container matColumnDef = " section " > < th mat-header-cell *matHeaderCellDef > Section </ th > < td mat-cell *matCellDef = " let element " > {{element.section}} </ td > </ ng-container > < ng-container matColumnDef = " action " > < th mat-header-cell *matHeaderCellDef > Action </ th > < td mat-cell *matCellDef = " let element; let i = index; " > < button mat-raised-button color = " primary " class = " push-right " [routerLink] = " ['/edit-student/', element._id] " > Edit </ button > < button mat-raised-button color = " accent " (click) = " deleteStudent(i, element) " > Delete </ button > </ td > </ ng-container > < tr mat-header-row *matHeaderRowDef = " displayedColumns " > </ tr > < tr mat-row *matRowDef = " let row; columns: displayedColumns; " > </ tr > </ table > < mat-paginator [pageSizeOptions] = " [5, 10, 20] " showFirstLastButtons > </ mat-paginator > </ div > </ div >

Edit Students Object in Mean Stack App We are going to create edit functionality using RESTful API in Mean stack app with Angular Material 8. Go to edit-list.component.ts file and add the following code. import { Router , ActivatedRoute } from '@angular/router' ; import { Component , OnInit , ViewChild , NgZone } from '@angular/core' ; import { COMMA , ENTER } from '@angular/cdk/keycodes' ; import { MatChipInputEvent } from '@angular/material' ; import { ApiService } from './../../shared/api.service' ; import { FormGroup , FormBuilder , Validators } from "@angular/forms" ; export interface Subject { name : string ; } @ Component ( { selector : 'app-edit-student' , templateUrl : './edit-student.component.html' , styleUrls : [ './edit-student.component.css' ] } ) export class EditStudentComponent implements OnInit { visible = true ; selectable = true ; removable = true ; addOnBlur = true ; @ ViewChild ( 'chipList' ) chipList ; @ ViewChild ( 'resetStudentForm' ) myNgForm ; readonly separatorKeysCodes : number [ ] = [ ENTER , COMMA ] ; studentForm : FormGroup ; subjectArray : Subject [ ] = [ ] ; SectioinArray : any = [ 'A' , 'B' , 'C' , 'D' , 'E' ] ; ngOnInit ( ) { this . updateBookForm ( ) ; } constructor ( public fb : FormBuilder , private router : Router , private ngZone : NgZone , private actRoute : ActivatedRoute , private studentApi : ApiService ) { var id = this . actRoute . snapshot . paramMap . get ( 'id' ) ; this . studentApi . GetStudent ( id ) . subscribe ( data => { console . log ( data . subjects ) this . subjectArray = data . subjects ; this . studentForm = this . fb . group ( { student_name : [ data . student_name , [ Validators . required ] ] , student_email : [ data . student_email , [ Validators . required ] ] , section : [ data . section , [ Validators . required ] ] , subjects : [ data . subjects ] , dob : [ data . dob , [ Validators . required ] ] , gender : [ data . gender ] } ) } ) } updateBookForm ( ) { this . studentForm = this . fb . group ( { student_name : [ '' , [ Validators . required ] ] , student_email : [ '' , [ Validators . required ] ] , section : [ '' , [ Validators . required ] ] , subjects : [ this . subjectArray ] , dob : [ '' , [ Validators . required ] ] , gender : [ 'Male' ] } ) } add ( event : MatChipInputEvent ) : void { const input = event . input ; const value = event . value ; if ( ( value || '' ) . trim ( ) && this . subjectArray . length < 5 ) { this . subjectArray . push ( { name : value . trim ( ) } ) } if ( input ) { input . value = '' ; } } remove ( subject : Subject ) : void { const index = this . subjectArray . indexOf ( subject ) ; if ( index >= 0 ) { this . subjectArray . splice ( index , 1 ) ; } } formatDate ( e ) { var convertDate = new Date ( e . target . value ) . toISOString ( ) . substring ( 0 , 10 ) ; this . studentForm . get ( 'dob' ) . setValue ( convertDate , { onlyself : true } ) } public handleError = ( controlName : string , errorName : string ) => { return this . studentForm . controls [ controlName ] . hasError ( errorName ) ; } updateStudentForm ( ) { console . log ( this . studentForm . value ) var id = this . actRoute . snapshot . paramMap . get ( 'id' ) ; if ( window . confirm ( 'Are you sure you want to update?' ) ) { this . studentApi . UpdateStudent ( id , this . studentForm . value ) . subscribe ( res => { this . ngZone . run ( ( ) => this . router . navigateByUrl ( '/students-list' ) ) } ) ; } } } Now go to edit-list.component.html file and add the following code. < div class = " title-group " > < h1 class = " mat-h1 " > Add Student </ h1 > < mat-divider fxFlex = " 1 0 " > </ mat-divider > </ div > < div class = " inner-wrapper " > < form [formGroup] = " studentForm " (ngSubmit) = " updateStudentForm() " #resetStudentForm = " ngForm " novalidate > < mat-card > < div class = " controlers-wrapper " > < mat-form-field class = " example-full-width " > < input matInput placeholder = " Student name " formControlName = " student_name " > < mat-error *ngIf = " handleError('student_name', 'required') " > You must provide a < strong > student name </ strong > </ mat-error > </ mat-form-field > < mat-form-field class = " example-full-width " > < input matInput placeholder = " Student email " formControlName = " student_email " > < mat-error *ngIf = " handleError('student_email', 'required') " > You must provide a < strong > student email </ strong > </ mat-error > </ mat-form-field > < mat-form-field > < mat-label > Section </ mat-label > < mat-select [(value)] = " selected " formControlName = " section " > < mat-option [value] = " sectioinArray " *ngFor = " let sectioinArray of SectioinArray " > {{sectioinArray}} </ mat-option > </ mat-select > < mat-error *ngIf = " handleError('section', 'required') " > Section is required </ mat-error > </ mat-form-field > </ div > </ mat-card > < mat-card > < div class = " controlers-wrapper " > < mat-form-field class = " multiple-items " > < mat-chip-list #chipList > < mat-chip *ngFor = " let subjectArray of subjectArray " [selectable] = " selectable " [removable] = " removable " (removed) = " remove(subjectArray) " > {{subjectArray.name}} < mat-icon matChipRemove *ngIf = " removable " > cancel </ mat-icon > </ mat-chip > < input placeholder = " Add subject " [matChipInputFor] = " chipList " [matChipInputSeparatorKeyCodes] = " separatorKeysCodes " [matChipInputAddOnBlur] = " addOnBlur " (matChipInputTokenEnd) = " add($event) " > </ mat-chip-list > < i class = " material-icons tooltip-info " matTooltip = " Enter subject name and press enter to add subjects " > info </ i > </ mat-form-field > < mat-form-field > < input matInput readonly [matDatepicker] = " picker " placeholder = " Date of birth " formControlName = " dob " (dateChange) = " formatDate($event) " > < mat-datepicker-toggle matSuffix [for] = " picker " > </ mat-datepicker-toggle > < mat-datepicker #picker > </ mat-datepicker > < mat-error *ngIf = " handleError('dob', 'required') " > Date of birth is required </ mat-error > </ mat-form-field > < div class = " misc-bottom-padding " > < mat-label > Gender: </ mat-label > < mat-radio-group aria-label = " Select an option " formControlName = " gender " > < mat-radio-button value = " Male " > Male </ mat-radio-button > < mat-radio-button value = " Female " > Female </ mat-radio-button > </ mat-radio-group > </ div > </ div > </ mat-card > < mat-card > < div class = " full-wrapper button-wrapper " > < div class = " button-wrapper " > < button mat-flat-button color = " warn " > Update </ button > </ div > </ div > </ mat-card > </ form > </ div >

Start The Mean Stack App Run the set of commands to start nodemon, MongoDB and Angular app to test the project. Start the Angular project: ng serve Start MongoDB:

I assume you have already set up MongoDB community edition in your local development system, if not then you can take the help from following tutorial.

https://docs.mongodb.com/manual/administration/install-community/ mongod -- config / usr / local / etc / mongod . conf brew services start mongodb - community@4 . 2 mongo Start the nodemon server: cd backend && nodemon I hope your Mean stack backend server is running fine, you can check your frontend and backend on the following URLs: Angular frontend URL:

http://localhost:4200 MEAN stack backend URL:

http://localhost:8000/api MEAN stack RESTful APIs using Express JS RESTful APIs Method API URL GET /api POST /add-student GET /read-student/id PUT /update-student/id DELETE /delete-student/id We can hit the below command in the terminal to check out how our newly created RESTful APIs are working. curl -i -H "Accept: application/json" localhost:8000/api If we are getting this type of response that means we are ready to go with our APIs. Or similarly we can also use Postmen API development environment tool to test our RESTful APIs.