Spring Boot + Angular CRUD Tutorial - Part #3 - Develop Angular CRUD Operations

In the previous Part 2, we have created an Angular 8 web application. 

In this Part 3 of Spring Boot + Angular 8 CRUD Example Tutorial, we will develop CRUD operations for an employee model using Angular 8.

Use the below links to visit different parts of this tutorial:

Table of contents

  1. Create an Employee class
  2. Employee Service
  3. Creating Employee List Template and Component
  4. Create Add Employee Template and Component
  5. Update Employee Template and Component
  6. Create View Employee Details Template and Component
The below diagram summaries the Angular components that we are going to create going forward:

1. Create an Employee Model (TypeScript)

Path - src/app/employee.ts
Before defining the EmployeeListComponent, let’s define an Employee class for working with employees. create a new file employee.ts inside src/app folder and add the following code to it -
export class Employee {
    id: number;
    firstName: string;
    lastName: string;
    emailId: string;
    active: boolean;
}

2. Creating Employee List Template and Component

Employee List Component

Path - src/app/employee-list/employee-list.component.ts
Let's create EmployeeListComponent component which will be used to display a list of employees, create a new employee, and delete an employee.
Update/remove the content of employee-list.component.ts inside src/app directory and add the following code to it -
import { EmployeeDetailsComponent } from '../employee-details/employee-details.component';
import { Observable } from "rxjs";
import { EmployeeService } from "../employee.service";
import { Employee } from "../employee";
import { Component, OnInit } from "@angular/core";
import { Router } from '@angular/router';

@Component({
  selector: "app-employee-list",
  templateUrl: "./employee-list.component.html",
  styleUrls: ["./employee-list.component.css"]
})
export class EmployeeListComponent implements OnInit {
  employees: Observable<Employee[]>;

  constructor(private employeeService: EmployeeService,
    private router: Router) {}

  ngOnInit() {
    this.reloadData();
  }

  reloadData() {
    this.employees = this.employeeService.getEmployeesList();
  }

  deleteEmployee(id: number) {
    this.employeeService.deleteEmployee(id)
      .subscribe(
        data => {
          console.log(data);
          this.reloadData();
        },
        error => console.log(error));
  }

  employeeDetails(id: number){
    this.router.navigate(['details', id]);
  }
}

Employee List Template

Path - src/app/employee-list/employee-list.component.html 
Add employee-list.component.html file with the following code to it -
<div class="panel panel-primary">
  <div class="panel-heading">
    <h2>Employee List</h2>
  </div>
  <div class="panel-body">
    <table class="table table-striped">
      <thead>
        <tr>
          <th>Firstname</th>
          <th>Lastname</th>
          <th>Email</th>
          <th>Actions</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let employee of employees | async">
          <td>{{employee.firstName}}</td>
          <td>{{employee.lastName}}</td>
          <td>{{employee.emailId}}</td>
          <td><button (click)="deleteEmployee(employee.id)" class="btn btn-danger">Delete</button>
              <button (click)="employeeDetails(employee.id)" class="btn btn-info" style="margin-left: 10px">Details</button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

3. Create Add Employee Template and Component

Create Employee Component

Path - src/app/create-employee/create-employee.component.ts
CreateEmployeeComponent is used to create and handle a new employee form data. Add the following code to it -
import { EmployeeService } from '../employee.service';
import { Employee } from '../employee';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-create-employee',
  templateUrl: './create-employee.component.html',
  styleUrls: ['./create-employee.component.css']
})
export class CreateEmployeeComponent implements OnInit {

  employee: Employee = new Employee();
  submitted = false;

  constructor(private employeeService: EmployeeService,
    private router: Router) { }

  ngOnInit() {
  }

  newEmployee(): void {
    this.submitted = false;
    this.employee = new Employee();
  }

  save() {
    this.employeeService
    .createEmployee(this.employee).subscribe(data => {
      console.log(data)
      this.employee = new Employee();
      this.gotoList();
    }, 
    error => console.log(error));
  }

  onSubmit() {
    this.submitted = true;
    this.save();    
  }

  gotoList() {
    this.router.navigate(['/employees']);
  }
}

Create Employee Template

Path - src/app/create-employee/create-employee.component.html
The create-employee.component.html shows the add employee HTML form. Add the following code to it -
<h3>Create Employee</h3>
<div [hidden]="submitted" style="width: 400px;">
  <form (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="name">First Name</label>
      <input type="text" class="form-control" id="firstName" required [(ngModel)]="employee.firstName" name="firstName">
    </div>

    <div class="form-group">
      <label for="name">Last Name</label>
      <input type="text" class="form-control" id="lastName" required [(ngModel)]="employee.lastName" name="lastName">
    </div>

    <div class="form-group">
      <label for="name">Email Id</label>
      <input type="text" class="form-control" id="emailId" required [(ngModel)]="employee.emailId" name="emailId">
    </div>

    <button type="submit" class="btn btn-success">Submit</button>
  </form>
</div>

<div [hidden]="!submitted">
  <h4>You submitted successfully!</h4>
  <!-- <button class="btn btn-success" (click)="newEmployee()">Add</button> -->
</div>

4. Update Employee Template and Component

Let's create update employee component with the following Angular CLI command:
> ng g c update-employee

Update Employee Component

Path - src/app/update-employee/update-employee.component.ts
UpdateEmployeeComponent is used to update an existing employee. 

In this UpdateEmployeeComponent, we first get the employee object using REST API and populate in HTML form via data binding. Users can edit the employee form data and submit the form.
 
Let's add the following code to UpdateEmployeeComponent -
import { Component, OnInit } from '@angular/core';
import { Employee } from '../employee';
import { ActivatedRoute, Router } from '@angular/router';
import { EmployeeService } from '../employee.service';

@Component({
  selector: 'app-update-employee',
  templateUrl: './update-employee.component.html',
  styleUrls: ['./update-employee.component.css']
})
export class UpdateEmployeeComponent implements OnInit {

  id: number;
  employee: Employee;

  constructor(private route: ActivatedRoute,private router: Router,
    private employeeService: EmployeeService) { }

  ngOnInit() {
    this.employee = new Employee();

    this.id = this.route.snapshot.params['id'];
    
    this.employeeService.getEmployee(this.id)
      .subscribe(data => {
        console.log(data)
        this.employee = data;
      }, error => console.log(error));
  }

  updateEmployee() {
    this.employeeService.updateEmployee(this.id, this.employee)
      .subscribe(data => {
        console.log(data);
        this.employee = new Employee();
        this.gotoList();
      }, error => console.log(error));
  }

  onSubmit() {
    this.updateEmployee();    
  }

  gotoList() {
    this.router.navigate(['/employees']);
  }
}

Update Employee Template

Path - src/app/update-employee/update-employee.component.html The update-employee.component.html shows the update employee HTML form. Add the following code to this file -
<h3>Update Employee</h3>
<div style="width: 400px;">
  <form (ngSubmit)="onSubmit()">
    <div class="form-group">
      <label for="name">First Name</label>
      <input type="text" class="form-control" id="firstName" required [(ngModel)]="employee.firstName" name="firstName">
    </div>

    <div class="form-group">
      <label for="name">Last Name</label>
      <input type="text" class="form-control" id="lastName" required [(ngModel)]="employee.lastName" name="lastName">
    </div>

    <div class="form-group">
      <label for="name">Email Id</label>
      <input type="text" class="form-control" id="emailId" required [(ngModel)]="employee.emailId" name="emailId">
    </div>

    <button type="submit" class="btn btn-success">Submit</button>
  </form>
</div>

5. Create View Employee Details Template and Component

Here we create view employee details functionality. Let's create an HTML template and component of Employee details functionality.

Employee Details Component

Path - src/app/employee-details/employee-details.component.ts
The EmployeeDetailsComponent component is used to display a particular employee detail. Add the following code to it -
import { Employee } from '../employee';
import { Component, OnInit, Input } from '@angular/core';
import { EmployeeService } from '../employee.service';
import { EmployeeListComponent } from '../employee-list/employee-list.component';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-employee-details',
  templateUrl: './employee-details.component.html',
  styleUrls: ['./employee-details.component.css']
})
export class EmployeeDetailsComponent implements OnInit {

  id: number;
  employee: Employee;

  constructor(private route: ActivatedRoute,private router: Router,
    private employeeService: EmployeeService) { }

  ngOnInit() {
    this.employee = new Employee();

    this.id = this.route.snapshot.params['id'];
    
    this.employeeService.getEmployee(this.id)
      .subscribe(data => {
        console.log(data)
        this.employee = data;
      }, error => console.log(error));
  }

  list(){
    this.router.navigate(['employees']);
  }
}

Employee Details Component Template

Path - src/app/employee-details/employee-details.component.html
The employee-details.component.html displays a particular employee detail. Add the following code to it -
<h2>Employee Details</h2> 

<hr/>
<div *ngIf="employee">
  <div>
    <label><b>First Name: </b></label> {{employee.firstName}}
  </div>
  <div>
    <label><b>Last Name: </b></label> {{employee.lastName}}
  </div>
  <div>
    <label><b>Email Id: </b></label> {{employee.emailId}}
  </div>  
</div>

<br>
<br>
<button (click)="list()" class="btn btn-primary">Back to Employee List</button><br>

6. Employee Service

Path - src/app/employee.service.ts
The EmployeeService will be used to get the data from the backend by calling spring boot APIs. Update the employee.service.ts file inside src/app directory with the following code to it -
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class EmployeeService {

  private baseUrl = 'http://localhost:8080/springboot-crud-rest/api/v1/employees';

  constructor(private http: HttpClient) { }

  getEmployee(id: number): Observable<any> {
    return this.http.get(`${this.baseUrl}/${id}`);
  }

  createEmployee(employee: Object): Observable<Object> {
    return this.http.post(`${this.baseUrl}`, employee);
  }

  updateEmployee(id: number, value: any): Observable<Object> {
    return this.http.put(`${this.baseUrl}/${id}`, value);
  }

  deleteEmployee(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`, { responseType: 'text' });
  }

  getEmployeesList(): Observable<any> {
    return this.http.get(`${this.baseUrl}`);
  }
}

This completed the development of CRUD operations using Angular 8.

Move to Part 4 - Angular 8 CRUD App Configuration

In this part 3,  we have developed CRUD operations for an employee model using Angular 8.

In the next Part 4, we will implement the following steps:
  • npm package.json - Configure Dependencies
  • App Routing Module
  • App Component
  • App Component Template
  • App Module
  • Main Index Html File
  • Main (Bootstrap) File
  • Polyfills
  • TypeScript tsconfig.json

Comments

  1. This is very helpful tutorial. I need a bit help on Update operation.Can you please share solution for Update.component.ts?

    ReplyDelete
    Replies
    1. Probably I am late in this comment. However, there is a variable declaration missing in update employee module. Pls see my remarks on Jul 19, 2020

      Delete
  2. Where does /springboot-crud-rest/ in the base url come from?

    ReplyDelete
    Replies
    1. I highly recommend you to watch video tutorial of this tutorial on my youtube channel.

      Delete
  3. I am wondering why you didn't have to declare the employee.service in the Provider section in the App module.

    ReplyDelete
  4. This is a great tutorial. I was able to complete this project and make it working in a couple of days.
    I typed in the source code as in the website. (I believe in typing the code so that I understand every line). After I got rid of my typo's, there was one error, which was due to omission of variable "submitted" in UpdateEmployeeComponent. The error was
    ERROR in src/app/update-employee/update-employee.component.html:3:16 - error TS2339: Property 'submitted' does not exist on type 'UpdateEmployeeComponent'.
    after I added the variable in UpdateEmployeeComponent (submnitted=false;) after the cline employee: Employee, the error went away.

    ReplyDelete
  5. i cant get the list of employee in the employee list componenet

    ReplyDelete
    Replies
    1. data is added in the database but not showing in the ui side

      Delete

Post a Comment

Leave Comment