Angular CRUD APP MEAN Stack Part – II

In the last article, we created server API for add, update, delete, and listing data. In this article, we discuss how to test API working or not and creating an Angular application to display the output.
After running the below command we start the API server.


npx nodemon server.js

It display the below Output in your Command Prompt scrren


[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] watching extension: js,mjs,json
[nodemon] starting `node server.js`
Connected to port 4000
Database sucessfully connected

Now we can check our api url on “http://localhost:4000/api
To test API you can run below command to get status of the URL.


curl -i -H "Accept: application/json" localhost:4000/api

It retruns 200 status then our REST API working properly. It display below output.


HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 2
ETag: W/"197-lywwuW2O7kr8CvBlt4zaMCqXZ0w"
Date: Sat, 03 OCT 2020 13:11:22 GMT
Connection: keep-alive



Now we need to set up the Angular application. To setup run the below command to create a new project of angular.


ng new curd-mean-demo

When running the above code it asking some question to set-up the project
1) Would you like to add Angular routing?: We need to enter “y” and hit the Enter key.
2) Which stylesheet format would you like to use? (Use arrow keys): I have used SCSS for this project using arrow key I select SCSS and hit the enter key.
After Successfully installed we need to go to the directory


cd curd-mean-demo

To open project in visual Studio Code then run “code .” to open project.
Let’s create a component for our application called employee to add, edit, and list. for that run the below command on the terminal.


ng g c components/employee-create
ng g c components/employee-edit
ng g c components/employee-list

After creating the component we need to set routing for the component. For that, we need to add the below code in the “app.routing.module.ts” file.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';


import { EmployeeCreateComponent } from './components/employee-create/employee-create.component';
import { EmployeeListComponent } from './components/employee-list/employee-list.component';
import { EmployeeEditComponent } from './components/employee-edit/employee-edit.component';


const routes: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'create-employee' },
  { path: 'create-employee', component: EmployeeCreateComponent },
  { path: 'edit-employee/:id', component: EmployeeEditComponent },
  { path: 'employees-list', component: EmployeeListComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Now we need to update “app.component.html” file to enable roting service for that we need to add “” Update file with below code.



<div class="container-fluid">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item"><a class="nav-link" routerLinkActive="active" routerLink="/employees-list">View Employees</a></li>
            <li class="nav-item"><a  class="nav-link" routerLinkActive="active" routerLink="/create-employee">Add Employee</a></li>
          </ul>

      </nav>

<router-outlet></router-outlet>
</div>

Now we need to create service which communicate with the OUR API server. First we need to add “HttpClientModule” in our “app.module.ts” file.


..
import { HttpClientModule } from '@angular/common/http';
...
@NgModule({
  imports: [
........
    HttpClientModule
   ]
})

After adding module lets create model class for emplyee data. Run below command to create model

ng g cl model/Employee

In that file we need to defind the filed with datatype.


export class Employee {
   name: string;
   email: string;
   designation: string;
   phoneNumber: number;
}

Now we need to create a Service wich communicates with REST API and our Application. To generate API run below command

ng g s service/api

In that file we add below code for add, edit, delete and get list data from the server.


import { Injectable } from '@angular/core';
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 {

  
  baseUri:string = 'http://localhost:4000/api';
  headers = new HttpHeaders().set('Content-Type', 'application/json');

  constructor(private http: HttpClient) { }

  // Create new employee
  createEmployee(data): Observable {
    let url = `${this.baseUri}/create`;
    return this.http.post(url, data)
      .pipe(
        catchError(this.errorMgmt)
      )
  }

  // Get all employees lists
  getEmployees() {
    return this.http.get(`${this.baseUri}`);
  }

  // Get employee by ID
  getEmployee(id): Observable {
    let url = `${this.baseUri}/read/${id}`;
    return this.http.get(url, {headers: this.headers}).pipe(
      map((res: Response) => {
        return res || {}
      }),
      catchError(this.errorMgmt)
    )
  }

  // Update employee
  updateEmployee(id, data): Observable {
    let url = `${this.baseUri}/update/${id}`;
    return this.http.put(url, data, { headers: this.headers }).pipe(
      catchError(this.errorMgmt)
    )
  }

  // Delete employee
  deleteEmployee(id): Observable {
    let url = `${this.baseUri}/delete/${id}`;
    return this.http.delete(url, { headers: this.headers }).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);
  }

}

After creating service we need to add in our “app.module.ts” file. Also FormGroup we used to create form for that we need to add ReactiveFormsModule


import { ApiService } from './service/api.service';
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
.....
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    ReactiveFormsModule
    
  ],
  providers: [ApiService]
})

Let’s create form in Component file called “employee.create.component.ts”. Add below code in that file.


import { Router } from '@angular/router';
import { ApiService } from './../../service/api.service';
import { Component, OnInit, NgZone } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from "@angular/forms";

@Component({
  selector: 'app-employee-create',
  templateUrl: './employee-create.component.html',
  styleUrls: ['./employee-create.component.scss']
})

export class EmployeeCreateComponent implements OnInit {  
  submitted = false;
  employeeForm: FormGroup;
  EmployeeProfile:any = ['PHP', 'Angular', 'Node', 'MEAN']
  
  constructor(
    public fb: FormBuilder,
    private router: Router,
    private ngZone: NgZone,
    private apiService: ApiService
  ) { 
    this.mainForm();
  }

  ngOnInit() { }

  mainForm() {
   
    this.employeeForm = this.fb.group({
      name: ['', [Validators.required]],
      email: ['', [Validators.required, Validators.email]],
      designation: ['', [Validators.required]],
      phoneNumber: ['', [Validators.required, Validators.pattern('^[0-9]+$')]]
    });

  }

  // Choose designation with select dropdown
  updateProfile(e){
    this.employeeForm.get('designation').setValue(e, {
      onlySelf: true
    })
  }

  // Getter to access form control
  get myForm(){
    return this.employeeForm.controls;
  }

  onSubmit() {
    this.submitted = true;
    if (!this.employeeForm.valid) {
      return false;
    } else {
      this.apiService.createEmployee(this.employeeForm.value).subscribe(
        (res) => {
          console.log('Employee successfully created!')
          this.ngZone.run(() => this.router.navigateByUrl('/employees-list'))
        }, (error) => {
          console.log(error);
        });
    }
  }

}


<div class="row justify-content-center">
  <div class="col-md-4 register-employee">

    <div class="card card-outline-secondary">
      <div class="card-header">
        <h3 class="mb-0">Add Employee</h3>
      </div>
    <!-- form card register -->
    <div class="card-body">
      <form [formGroup]="employeeForm" (ngSubmit)="onSubmit()">
        <div class="form-group">
          <label for="inputName">Name</label>
          <input class="form-control" type="text" formControlName="name">
          <!-- error -->
          <div class="invalid-feedback" *ngIf="submitted && myForm.name.errors?.required">
            Name is required.
          </div>
          
        </div>

        <div class="form-group">
          <label for="inputEmail3">Email</label>
          <input class="form-control" type="text" formControlName="email">
          <!-- error -->
          <div class="invalid-feedback" *ngIf="submitted && myForm.email.errors?.required">
            Enter your email.
          </div>
          <div class="invalid-feedback" *ngIf="submitted && myForm.email.errors?.email">
            Enter valid email.
          </div>
        </div>

        <div class="form-group">
          <label for="inputPassword3">Designation</label>
          <select class="custom-select form-control" (change)="updateProfile($event.target.value)"
            formControlName="designation">
            <option value="">Choose...</option>
            <option *ngFor="let employeeProfile of EmployeeProfile" value="{{employeeProfile}}">{{employeeProfile}}
            </option>
          </select>
          <!-- error -->
          <div class="invalid-feedback" *ngIf="submitted && myForm.designation.errors?.required">
            Choose designation.
          </div>
        </div>

        <div class="form-group">
          <label for="inputVerify3">Mobile No</label>
          <input class="form-control" type="text" formControlName="phoneNumber">
          <!-- error -->
          <div class="invalid-feedback" *ngIf="submitted && myForm.phoneNumber.errors?.required">
            Enter your phone number.
          </div>
          <div class="invalid-feedback" *ngIf="submitted && myForm.phoneNumber.errors?.pattern">
            Enter Numbers Only
          </div>
        </div>

        <div class="form-group">
          <button class="btn btn-primary btn-lg btn-block" type="submit">Register</button>
        </div>
      </form>

    </div>
    </div>
  </div><!-- form card register -->
</div>

Employees List Component


import { Component, OnInit } from '@angular/core';
import { ApiService } from './../../service/api.service';

@Component({
  selector: 'app-employee-list',
  templateUrl: './employee-list.component.html',
  styleUrls: ['./employee-list.component.scss']
})

export class EmployeeListComponent implements OnInit {
  
  Employee:any = [];

  constructor(private apiService: ApiService) { 
    this.readEmployee();
  }

  ngOnInit() {}

  readEmployee(){
    this.apiService.getEmployees().subscribe((data) => {
     this.Employee = data;
    })    
  }

  removeEmployee(employee, index) {
    if(window.confirm('Are you sure?')) {
        this.apiService.deleteEmployee(employee._id).subscribe((data) => {
          this.Employee.splice(index, 1);
        }
      )    
    }
  }

}


<div class="container">
    <!-- No data message -->
    <div *ngIf="Employee.length <= 0">
      <p class="alet alert-warning text-center">There is no employee added yet!</p>
    </div>
  
  
    <!-- Employee list -->
    <table class="table table-bordered" *ngIf="Employee.length > 0">
      <thead class="table-primary">
        <tr>
          <th scope="col">Employee ID</th>
          <th scope="col">Name</th>
          <th scope="col">Email</th>
          <th scope="col">Designation</th>
          <th scope="col">Phone No</th>
          <th scope="col center">Update</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let employee of Employee; let i = index">
          <th scope="row">{{employee._id}}</th>
          <td>{{employee.name}}</td>
          <td>{{employee.email}}</td>
          <td>{{employee.designation}}</td>
          <td>{{employee.phoneNumber}}</td>
          <td class="text-center edit-block">
            <span class="edit" [routerLink]="['/edit-employee/', employee._id]">
              <button type="button" class="btn btn-primary btn-sm">Edit</button>
            </span>
            <span class="delete" (click)="removeEmployee(employee, i)">
              <button type="button" class="btn btn-danger btn-sm">Delete</button>
            </span>
          </td>
        </tr>
      </tbody>
    </table>
  </div>




Employee Edit Component


import { Employee } from './../../model/Employee';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from "@angular/router";
import { ApiService } from './../../service/api.service';
import { FormGroup, FormBuilder, Validators } from "@angular/forms";


@Component({
  selector: 'app-employee-edit',
  templateUrl: './employee-edit.component.html',
  styleUrls: ['./employee-edit.component.scss']
})

export class EmployeeEditComponent implements OnInit {
  submitted = false;
  editForm: FormGroup;
  employeeData: Employee[];
  EmployeeProfile: any = ['PHP', 'Angular', 'Node', 'MEAN']

  constructor(
    public fb: FormBuilder,
    private actRoute: ActivatedRoute,
    private apiService: ApiService,
    private router: Router
  ) {}

  ngOnInit() {
    this.updateEmployee();
    let id = this.actRoute.snapshot.paramMap.get('id');
    this.getEmployee(id);
    this.editForm = this.fb.group({
      name: ['', [Validators.required]],
      email: ['', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')]],
      designation: ['', [Validators.required]],
      phoneNumber: ['', [Validators.required, Validators.pattern('^[0-9]+$')]]
    })
  }

  // Choose options with select-dropdown
  updateProfile(e) {
    this.editForm.get('designation').setValue(e, {
      onlySelf: true
    })
  }

  // Getter to access form control
  get myForm() {
    return this.editForm.controls;
  }

  getEmployee(id) {
    this.apiService.getEmployee(id).subscribe(data => {
      this.editForm.setValue({
        name: data['name'],
        email: data['email'],
        designation: data['designation'],
        phoneNumber: data['phoneNumber'],
      });
    });
  }

  updateEmployee() {
    this.editForm = this.fb.group({
      name: ['', [Validators.required]],
      email: ['', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')]],
      designation: ['', [Validators.required]],
      phoneNumber: ['', [Validators.required, Validators.pattern('^[0-9]+$')]]
    })
  }

  onSubmit() {
    this.submitted = true;
    if (!this.editForm.valid) {
      return false;
    } else {
      if (window.confirm('Are you sure?')) {
        let id = this.actRoute.snapshot.paramMap.get('id');
        this.apiService.updateEmployee(id, this.editForm.value)
          .subscribe(res => {
            this.router.navigateByUrl('/employees-list');
            console.log('Content updated successfully!')
          }, (error) => {
            console.log(error)
          })
      }
    }
  }

}


<div class="row justify-content-center">
    <div class="col-md-4 register-employee">
      <!-- form card register -->
      <div class="card card-outline-secondary">
        <div class="card-header">
          <h3 class="mb-0">Edit Employee</h3>
        </div>
        <div class="card-body">
          <form [formGroup]="editForm" (ngSubmit)="onSubmit()">
 
            <div class="form-group">
              <label for="inputName">Name</label>
              <input class="form-control" type="text" formControlName="name">
              <div class="invalid-feedback" *ngIf="submitted && myForm.name.errors?.required">
                Name is required.
              </div>
            </div>
            <div class="form-group">
              <label for="inputEmail3">Email</label>
              <input class="form-control" type="text" formControlName="email">
              <!-- error -->
              <div class="invalid-feedback" *ngIf="submitted && myForm.email.errors?.required">
                Enter your email.
              </div>
              <div class="invalid-feedback" *ngIf="submitted && myForm.email.errors?.pattern">
                Enter valid email.
              </div>
            </div>
 
            <div class="form-group">
              <label for="inputPassword3">Designation</label>
              <select class="custom-select form-control" (change)="updateProfile($event.target.value)"
                formControlName="designation">
                <option value="">Choose...</option>
                <option *ngFor="let employeeProfile of EmployeeProfile" value="{{employeeProfile}}">{{employeeProfile}}
                </option>
              </select>
              <!-- error -->
              <div class="invalid-feedback" *ngIf="submitted && myForm.designation.errors?.required">
                Choose designation.
              </div>
            </div>
 
            <div class="form-group">
              <label for="inputVerify3">Mobile No</label>
              <input class="form-control" type="text" formControlName="phoneNumber">
              <!-- error -->
              <div class="invalid-feedback" *ngIf="submitted && myForm.phoneNumber.errors?.required">
                Enter your phone number.
              </div>
              <div class="invalid-feedback" *ngIf="submitted && myForm.phoneNumber.errors?.pattern">
                Enter Numbers Only
              </div>
            </div>
 
            <div class="form-group">
              <button class="btn btn-primary btn-lg btn-block" type="submit">Update</button>
            </div>
          </form>
        </div>
      </div><!-- form  -->
    </div>
  </div>
 


Output

Spread the love
  •  
  •  
  •  
  •  
  •  
  • 3
  •  
  •