In this article we will be building
an Angular 6 CRUD Operation application step by step from scratch with example.
We will be generating our Angular 6 application using angular CLI and then
modify it to have an employee management project where end user can perform
CRUD operations such as create, list, update and delete with the sample REST
API exposed using HttpClientModule. We will also be using RouterModule to have
routing enabled.
For this project, I have npm 5.6.0 and node
v8.11.2 installed on my local system. You can download the latest version of
Node js from here https://nodejs.org/en/download/. To update NPM, you can run
the following command in the terminal.
If u have a @angular/cli version older then 6,
then run following command to install the latest versions:
npm
uninstall -g @angular/cli
npm
cache clean
npm
install -g @angular/cli
To install a specific version, you can
use npm install -g @angular/cli@6.1.6
Generating Angular 6 Project
Once,
the npm and node is upgraded to the latest version, you can run following
command to generate angular 6 project in any location of your choice.
Doing
so, our angular 6 application is generated.
Angular 6 Project Structure
Once
the project is generated, you can run following commands to see angular 6 app
running at localhost:4200.
cd crudoperation
ng serve
Routing
Following is our routing configuration.
We have configured to use ListEmpComponent as a default component. Also, do not
forget to include it in the main module - app.module.ts
app-routing.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { ListEmpComponent } from './list-emp/list-emp.component';
import { AddEmpComponent } from './add-emp/add-emp.component';
export const routes: Routes = [
{ path: '', component: ListEmpComponent, pathMatch: 'full' },
{ path: 'list-emp', component: ListEmpComponent },
{ path: 'add-emp', component: AddEmpComponent }
];
@NgModule({
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
exports: [RouterModule],
declarations: []
})
export class AppRoutingModule { }
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { ReactiveFormsModule } from "@angular/forms";
import { AppComponent } from './app.component';
import { ListEmpComponent } from './list-emp/list-emp.component';
import { AddEmpComponent } from './add-emp/add-emp.component';
import { EmployeeService } from './service/employee.service';
@NgModule({
declarations: [
AppComponent,
ListEmpComponent,
AddEmpComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
ReactiveFormsModule
],
providers: [EmployeeService],
bootstrap: [AppComponent]
})
export class AppModule { }
Model
export class Employee {
id?: number;
employee_name?: string;
employee_salary?: number;
employee_age?: number;
}
Service
Following is the implementation
of our EmployeeService. It has all the API details that is required for the
CRUD operation. Here, I have used Json Server for making API calls.
Json Server is for front-end
developers which simulates a backend REST service to deliver data
in JSON format to the front-end application and make sure everything
is working as expected.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Employee } from '../model/employee.model';
@Injectable({
providedIn: 'root'
})
export class EmployeeService {
constructor(private http: HttpClient) { }
baseUrl: string = 'http://localhost:3004/posts/';
getEmployees() {
return this.http.get<Employee[]>(this.baseUrl);
}
deleteEmployees(id: number) {
return this.http.delete<Employee[]>(this.baseUrl + id);
}
createUser(employee: Employee) {
return this.http.post(this.baseUrl, employee);
}
getEmployeeById(id: number) {
return this.http.get<Employee>(this.baseUrl + '/' + id);
}
updateEmployee(employee: Employee) {
return this.http.put(this.baseUrl + '/' + employee.id, employee);
}
}
Creating Components
list-emp.component.html
<div class="col-md-12">
<h2> User Details</h2>
<div class="table-responsive table-container">
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Employee Name</th>
<th>Salary</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let emp of employees">
<td class="hidden">{{emp.id}}</td>
<td>{{emp.employee_name}}</td>
<td>{{emp.employee_salary}}</td>
<td>{{emp.employee_age}}</td>
<td>
<button (click)="deleteEmp(emp)" class="btn btn-info"> Delete</button>
<button (click)="editEmp(emp)" style="margin-left: 20px;" class="btn
btn-info"> Edit</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
list-emp.component.ts
import { Component, OnInit } from '@angular/core';
import { EmployeeService } from '../service/employee.service';
import { Employee } from '../model/employee.model';
import { Router } from "@angular/router";
@Component({
selector: 'app-list-emp',
templateUrl: './list-emp.component.html',
styleUrls: ['./list-emp.component.css']
})
export class ListEmpComponent implements OnInit {
employees: Employee[];
constructor(private empService: EmployeeService, private router: Router, ) { }
ngOnInit() {
this.empService.getEmployees()
.subscribe((data: Employee[]) => {
this.employees = data;
});
}
deleteEmp(employee: Employee): void {
this.empService.deleteEmployees(employee.id)
.subscribe(data => {
this.employees = this.employees.filter(u => u !== employee);
})
}
editEmp(employee: Employee): void {
localStorage.removeItem('editEmpId');
localStorage.setItem('editEmpId', employee.id.toString());
this.router.navigate(['add-emp']);
}
}
add-emp.component.html
<div class="col-md-6">
<h2 class="text-center">{{empformlabel}}</h2>
<form [formGroup]="addForm" novalidate class="form">
<div class="form-group">
<label for="empId">Employee Id:</label>
<input type="number" formControlName="id" placeholder="Id" name="empId" class="form-control" id="empId">
</div>
<div class="form-group">
<label for="empName">Employee Name:</label>
<input formControlName="employee_name" placeholder="Employee Name" name="empName" class="form-control" id="empName">
<div class="alert
alert-danger" *ngIf="addForm.get('employee_name').hasError('required')
&& addForm.get('employee_name').touched">
Employee Name is required
</div>
</div>
<div class="form-group">
<label for="empSalary">Employee Salary:</label>
<input formControlName="employee_salary" placeholder="Employee Salary" name="employee_salary" class="form-control" id="employee_salary">
<div class="alert
alert-danger" *ngIf="addForm.get('employee_salary').hasError('maxlength')
&& addForm.get('employee_salary').touched">
Employee Salary is required and should
less than 9 characters.
</div>
</div>
<div class="form-group">
<label for="empAge">Employee Age:</label>
<input formControlName="employee_age" placeholder="Employee Age" name="empAge" class="form-control" id="empAge">
<div class="alert
alert-danger" *ngIf=" addForm.get('employee_age').hasError('maxlength')
&& addForm.get('employee_age').touched">
Age is required and should less than 3
characters.
</div>
</div>
<button class="btn btn-success" [disabled]='addForm.invalid' *ngIf="btnvisibility" (click)="onSubmit()">Save</button>
<button class="btn btn-success" [disabled]='addForm.invalid' *ngIf="!btnvisibility" (click)="onUpdate()">Update</button>
<p>Form value: {{ addForm.value | json }}</p>
</form>
</div>
add-emp.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { EmployeeService } from '../service/employee.service';
import { Router } from "@angular/router";
@Component({
selector: 'app-add-emp',
templateUrl: './add-emp.component.html',
styleUrls: ['./add-emp.component.css']
})
export class AddEmpComponent implements OnInit {
empformlabel: string = 'Add Employee';
empformbtn: string = 'Save';
constructor(private formBuilder: FormBuilder, private router: Router, private empService: EmployeeService) {
}
addForm: FormGroup;
btnvisibility: boolean = true;
ngOnInit() {
this.addForm = this.formBuilder.group({
id: [],
employee_name: ['', Validators.required],
employee_salary: ['', [Validators.required, Validators.maxLength(9)]],
employee_age: ['', [Validators.required, Validators.maxLength(3)]]
});
let empid = localStorage.getItem('editEmpId');
if (+empid > 0) {
this.empService.getEmployeeById(+empid).subscribe(data => {
this.addForm.patchValue(data);
})
this.btnvisibility = false;
this.empformlabel = 'Edit Employee';
this.empformbtn = 'Update';
}
}
onSubmit() {
console.log('Create fire');
this.empService.createUser(this.addForm.value)
.subscribe(data => {
this.router.navigate(['list-emp']);
},
error => {
alert(error);
});
}
onUpdate() {
console.log('Update fire');
this.empService.updateEmployee(this.addForm.value).subscribe(data => {
this.router.navigate(['list-emp']);
},
error => {
alert(error);
});
}
}
Global Style
style.css
/* You can add global
styles to this file, and also import other style files */
@import "~bootstrap/dist/css/bootstrap.css";
@import "~font-awesome/css/font-awesome.css";
.ng-valid[required], .ng-valid.required {
border-left: 5px solid #42A948; /* green */
}
.ng-invalid:not(form) {
border-left: 5px solid #a94442; /* red */
}
.mtop10{
margin-top:10px;
}
Testing Angular 6
Application
Now run the command ng
serve and hit localhost:4200
You can see following screen with
list of users. On this page, you can perform actions to add, edit and delete employee.
Here, we have used same Component
for Add and Edit/Update Employee.
Conclusion