In this tutorial, you’ll learn Angular 8 MEAN Stack tutorial and how to build an Angular 8 CRUD web application from MEAN 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:
I’ll create application’s frontend in Angular 8 using Angular material 8 UI components and backend with Node js, Expressjs 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.
Firstly, you need to have Node.js and Angular CLI installed in your system to work with Angular 8 Mean stack project. To install Node.js in 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 8.
We are going to build a MEAN stack web app using Angular 8. In our MEAN stack web app, we’ll use the Angular 8 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:
# ? Would you like to add Angular routing? = Yes
# ? Which stylesheet format would you like to use? = CSS
Head over to the newly created Angular 8 project’s directory using below cmd.
cd angular8-meanstack-angular-material
In next step we’ll create three new components to manage Angular 8 Mean stack Angular CRUD app. Use Angular 8 CLI to generate Angular 8 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 thatapp.module.ts
is our main app module file.
In this part of the tutorial we’ll create routes in our Mean stack angular 8 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 { }
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 Angular 8 CRUD app with following Angular material UI components:
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 Angular 8 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 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.
/* Angular material */
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 { }
Go to app.component.html
file and include the following code.
Student Records
menu
<mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'over' : 'side'" [(opened)]="opened" [fixedInViewport]="true"
[fixedTopGap]>
add Add Student
format_list_bulleted View Students
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.
In this part of the tutorial, we are going to build a robust Mean stack backend using mongoDB, nodejs, and expressjs.
Following topics will be covered in this part of the tutorial:
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
After that install the required dependencies for your Angular 8 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 Angular 8 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"
}
}
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'
};
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;
// Define collection and 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)
In this Angular 8 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();
// Student model
let Student = require('../model/Student');
// Add Student
studentRoute.route('/add-student').post((req, res, next) => {
Student.create(req.body, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
});
// Get all student
studentRoute.route('/').get((req, res) => {
Student.find((error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
// Get single student
studentRoute.route('/read-student/:id').get((req, res) => {
Student.findById(req.params.id, (error, data) => {
if (error) {
return next(error)
} else {
res.json(data)
}
})
})
// Update student
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!')
}
})
})
// Delete student
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;
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
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.
let express = require('express'),
path = require('path'),
mongoose = require('mongoose'),
cors = require('cors'),
bodyParser = require('body-parser'),
dataBaseConfig = require('./database/db');
// Connecting mongoDB
mongoose.Promise = global.Promise;
mongoose.connect(dataBaseConfig.db, {
useNewUrlParser: true
}).then(() => {
console.log('Database connected sucessfully ')
},
error => {
console.log('Could not connected to database : ' + error)
}
)
// Set up express js port
const studentRoute = require('../backend/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('/', express.static(path.join(__dirname, 'dist/angular8-meanstack-angular-material')));
app.use('/api', studentRoute)
// Create port
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
console.log('Connected to port ' + port)
})
// Find 404 and hand over to error handler
app.use((req, res, next) => {
next(createError(404));
});
// 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);
});
Everything has been placed at its place, now we have to start the Angular 8 project, mongoDB server and Nodemon server.
Run the following commands…
Start the Angular project:
ng serve
Initialise the mongoDB database:
cd backend && mongod
Start the nodemon server:
cd backend && nodemon
I hope your Angular 8 Mean stack backend server is running fine, you can check your frontend and backend on the following URLs:
Angular frontend URL:
MEAN stack backend URL:
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:4000/api
# HTTP/1.1 200 OK
# X-Powered-By: Express
# Access-Control-Allow-Origin: *
# Content-Type: application/json; charset=utf-8
# Content-Length: 58
# ETag: W/"3a-dzxOuKmgt3HAevjaPlycYSK+FhI"
# Date: Sun, 26 May 2019 18:53:03 GMT
# Connection: keep-alive
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.
To create Angular 8 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.
Import HttpClientModule
service in app.module.ts
file.
/* Angular 8 http service */
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
HttpClientModule
]
})
Enter the below command to create model > student.ts
file.
export class Student {
_id: String;
student_name: String;
student_email: String;
section: String;
subjects: Array;
dob: Date;
gender: String;
}
Enter the following command to create Angular 8 service to manage CRUD operations in Angular 8 MEAN Stack web app.
ng g s shared/api
In the given below code we’ve consumed REST APIs using Angular 8 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:4000/api';
headers = new HttpHeaders().set('Content-Type', 'application/json');
constructor(private http: HttpClient) { }
// Add student
AddStudent(data: Student): Observable {
let API_URL = `${this.endpoint}/add-student`;
return this.http.post(API_URL, data)
.pipe(
catchError(this.errorMgmt)
)
}
// Get all students
GetStudents() {
return this.http.get(`${this.endpoint}`);
}
// Get student
GetStudent(id): Observable {
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)
)
}
// Update student
UpdateStudent(id, data: Student): Observable {
let API_URL = `${this.endpoint}/update/${id}`;
return this.http.put(API_URL, data, { headers: this.headers }).pipe(
catchError(this.errorMgmt)
)
}
// Delete student
DeleteStudent(id): Observable {
var API_URL = `${this.endpoint}/delete-student/${id}`;
return this.http.delete(API_URL).pipe(
catchError(this.errorMgmt)
)
}
// Error handling
errorMgmt(error: HttpErrorResponse) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
console.log(errorMessage);
return throwError(errorMessage);
}
}
Go to app.module.ts
file and import this API service like given below.
/* Angular 8 CRUD services */
import { ApiService } from './shared/api.service';
@NgModule({
providers: [ApiService]
})
In this part of the tutorial we will learn to add student in the MongoDB database. We’ll be using Angular 8 Reactive form to add student in the database.
In order to work with Angular 8 Reactive Forms we must import the ReactiveFormsModule API and FormsModule
API in app.module.ts
file.
/* Reactive form services in Angular 8 */
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
) { }
/* Reactive book form */
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 dynamic languages */
add(event: MatChipInputEvent): void {
const input = event.input;
const value = event.value;
// Add language
if ((value || '').trim() && this.subjectArray.length < 5) {
this.subjectArray.push({ name: value.trim() })
}
// Reset the input value
if (input) {
input.value = '';
}
}
/* Remove dynamic languages */
remove(subject: Subject): void {
const index = this.subjectArray.indexOf(subject);
if (index >= 0) {
this.subjectArray.splice(index, 1);
}
}
/* Date */
formatDate(e) {
var convertDate = new Date(e.target.value).toISOString().substring(0, 10);
this.studentForm.get('dob').setValue(convertDate, {
onlyself: true
})
}
/* Get errors */
public handleError = (controlName: string, errorName: string) => {
return this.studentForm.controls[controlName].hasError(errorName);
}
/* Submit book */
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.
# Add Student
You must provide a**student name**
You must provide a**student email**
Section
{{sectioinArray}}
Section is required
<mat-chip *ngFor="let subjectArray of subjectArray" [selectable]="selectable" [removable]="removable"
(removed)="remove(subjectArray)">
{{subjectArray.name}}
cancel
<input placeholder="Add subject" [matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)">
info
<input matInput readonly [matDatepicker]="picker" placeholder="Date of birth" formControlName="dob"
(dateChange)="formatDate($event)">
Date of birth is required
Gender:
Male
Female
Submit
Go to students-list.component.ts
file and add the given below code. In this file, we’ll manage the following tasks.
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;
@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(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.
# Students List
There is no student added yet!
0">
Student ID
{{element._id}}
Student Name
{{element.student_name}}
Email
{{element.student_email}}
Section
{{element.section}}
Action
<button mat-raised-button color="primary" class="push-right"
[routerLink]="['/edit-student/', element._id]">Edit
Delete
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]
})
})
}
/* Reactive book form */
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 dynamic languages */
add(event: MatChipInputEvent): void {
const input = event.input;
const value = event.value;
// Add language
if ((value || '').trim() && this.subjectArray.length < 5) {
this.subjectArray.push({ name: value.trim() })
}
// Reset the input value
if (input) {
input.value = '';
}
}
/* Remove dynamic languages */
remove(subject: Subject): void {
const index = this.subjectArray.indexOf(subject);
if (index >= 0) {
this.subjectArray.splice(index, 1);
}
}
/* Date */
formatDate(e) {
var convertDate = new Date(e.target.value).toISOString().substring(0, 10);
this.studentForm.get('dob').setValue(convertDate, {
onlyself: true
})
}
/* Get errors */
public handleError = (controlName: string, errorName: string) => {
return this.studentForm.controls[controlName].hasError(errorName);
}
/* Update book */
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.
# Add Student
You must provide a**student name**
You must provide a**student email**
Section
{{sectioinArray}}
Section is required
<mat-chip *ngFor="let subjectArray of subjectArray" [selectable]="selectable" [removable]="removable"
(removed)="remove(subjectArray)">
{{subjectArray.name}}
cancel
<input placeholder="Add subject" [matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)">
info
<input matInput readonly [matDatepicker]="picker" placeholder="Date of birth" formControlName="dob"
(dateChange)="formatDate($event)">
Date of birth is required
Gender:
Male
Female
Update
Finally, we have created a basic Angular 8 MEAN stack CRUD web app with Angular Material. Anyhow, if we have missed anything you can check out GitHub repo of this project.
#angular #web-development #node-js #express #mongodb