📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.
🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.
▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube
Angular is a platform and framework for building client applications in HTML and TypeScript. Angular is written in TypeScript. It implements core and optional functionality as a set of TypeScript libraries that you import into your apps.
In this Angular 8 application, we will be consuming Spring boot CRUD rest API exposed at Spring Boot 2 JPA MySQL CRUD Example article.
If you are looking for Angular 8 with spring boot 2 integration example then check out Spring Boot + Angular 8 CRUD Example Tutorial article.
The source code of this tutorial available on my GitHub repository(the link has given at the end of this tutorial).
Check out Angular 9 tutorials at https://www.javaguides.net/p/angular-9-tutorial.html
Check out the latest Angular 9 CRUD Example Tutorial.
Angular 10 + Spring Boot CRUD Full Stack Application - Free Course
Features Implementation
- Create an Employee
- Update an Employee
- List of Employees
- Delete Employee
- View Employee
- You will develop your first FULL STACK Application with Angular 8 and Spring Boot.
What we will build?
Add Employee Page
Delete Employee
Angular 8 CRUD App Development
C:\Angular>node -v
v10.15.3
C:\Angular>npm -v
6.9.0
Install the latest version of Angular CLI
npm install -g @angular/cli
C:\angular>ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 8.0.1
Node: 10.15.3
OS: win32 x64
Angular:
...
Package Version
------------------------------------------------------
@angular-devkit/architect 0.800.1
@angular-devkit/core 8.0.1
@angular-devkit/schematics 8.0.1
@schematics/angular 8.0.1
@schematics/update 0.800.1
rxjs 6.4.0
Create Angular 8 Client Application using Angular CLI
ng new angular8-springboot-client
Identify Components, Services, and Modules
Components
- create-employee
- employee-list
- employee-details
- update-employee
Services
- employee.service.ts - Service for Http Client methods
Modules
- FormsModule
- HttpClientModule
- AppRoutingModule
Employee Class (Typescript class)
- employee.ts: class Employee (id, firstName, lastName, emailId)
Create Service & Components using Angular CLI
- ng g s employee
– ng g c create-employee
– ng g c employee-details
– ng g c employee-list
C:\Angular\angular8-springboot-crud-tutorial\angular8-springboot-client>cd src/app
C:\Angular\angular8-springboot-crud-tutorial\angular8-springboot-client\src\app>ng g s employee
CREATE src/app/employee.service.spec.ts (343 bytes)
CREATE src/app/employee.service.ts (137 bytes)
C:\Angular\angular8-springboot-crud-tutorial\angular8-springboot-client\src\app>ng g c create-employee
CREATE src/app/create-employee/create-employee.component.html (34 bytes)
CREATE src/app/create-employee/create-employee.component.spec.ts (685 bytes)
CREATE src/app/create-employee/create-employee.component.ts (304 bytes)
CREATE src/app/create-employee/create-employee.component.css (0 bytes)
UPDATE src/app/app.module.ts (509 bytes)
C:\Angular\angular8-springboot-crud-tutorial\angular8-springboot-client\src\app>ng g c employee-list
CREATE src/app/employee-list/employee-list.component.html (32 bytes)
CREATE src/app/employee-list/employee-list.component.spec.ts (671 bytes)
CREATE src/app/employee-list/employee-list.component.ts (296 bytes)
CREATE src/app/employee-list/employee-list.component.css (0 bytes)
UPDATE src/app/app.module.ts (617 bytes)
C:\Angular\angular8-springboot-crud-tutorial\angular8-springboot-client\src\app>ng g c employee-list
ERROR! src/app/employee-list/employee-list.component.html already exists.
ERROR! src/app/employee-list/employee-list.component.spec.ts already exists.
ERROR! src/app/employee-list/employee-list.component.ts already exists.
ERROR! src/app/employee-list/employee-list.component.css already exists.
The Schematic workflow failed. See above.
C:\Angular\angular8-springboot-crud-tutorial\angular8-springboot-client\src\app>ng g c employee-details
CREATE src/app/employee-details/employee-details.component.html (35 bytes)
CREATE src/app/employee-details/employee-details.component.spec.ts (692 bytes)
CREATE src/app/employee-details/employee-details.component.ts (308 bytes)
CREATE src/app/employee-details/employee-details.component.css (0 bytes)
UPDATE src/app/app.module.ts (737 bytes)
Integrate JQuery and Bootstrap with Angular
npm install bootstrap jquery --save
...
"styles": [
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
...
/* You can add global styles to this file, and also import other style files */
@import '~bootstrap/dist/css/bootstrap.min.css';
.footer {
position: absolute;
bottom: 0;
width:100%;
height: 70px;
background-color: blue;
text-align: center;
color: white;
}
Create an Employee Model (TypeScript)
export class Employee {
id: number;
firstName: string;
lastName: string;
emailId: string;
active: boolean;
}
Creating Employee List Template and Component
Employee List Component
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
<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>
Create Add Employee Template and Component
Create Employee Component
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
<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">First Name</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>
Update Employee Template and Component
> ng g c update-employee
Update Employee Component
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
<h3>Update 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">First Name</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>
Create View Employee Details Template and Component
Employee Details Component
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
<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>
Employee Service
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}`);
}
}
npm package.json - Configure Dependencies
{
"name": "angular8-springboot-client",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~8.0.0",
"@angular/common": "~8.0.0",
"@angular/compiler": "~8.0.0",
"@angular/core": "~8.0.0",
"@angular/forms": "~8.0.0",
"@angular/platform-browser": "~8.0.0",
"@angular/platform-browser-dynamic": "~8.0.0",
"@angular/router": "~8.0.0",
"bootstrap": "^4.3.1",
"jquery": "^3.4.1",
"rxjs": "~6.4.0",
"tslib": "^1.9.0",
"zone.js": "^0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.800.0",
"@angular/cli": "~8.0.1",
"@angular/compiler-cli": "~8.0.0",
"@angular/language-service": "~8.0.0",
"@types/node": "~8.9.4",
"@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "^5.0.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.4.3"
}
}
App Routing Module
import { EmployeeDetailsComponent } from './employee-details/employee-details.component'; import { CreateEmployeeComponent } from './create-employee/create-employee.component'; import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { EmployeeListComponent } from './employee-list/employee-list.component'; import { UpdateEmployeeComponent } from './update-employee/update-employee.component'; const routes: Routes = [ { path: '', redirectTo: 'employee', pathMatch: 'full' }, { path: 'employees', component: EmployeeListComponent }, { path: 'add', component: CreateEmployeeComponent }, { path: 'update/:id', component: UpdateEmployeeComponent }, { path: 'details/:id', component: EmployeeDetailsComponent }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
App Component
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Angular 8 + Spring Boot 2 CRUD Tutorial';
}
App Component Template
<nav class="navbar navbar-expand-sm bg-primary navbar-dark">
<!-- Links -->
<ul class="navbar-nav">
<li class="nav-item">
<a routerLink="employees" class="nav-link" routerLinkActive="active">Employee List</a>
</li>
<li class="nav-item">
<a routerLink="add" class="nav-link" routerLinkActive="active">Add Employee</a>
</li>
</ul>
</nav>
<div class="container">
<br>
<h2 style="text-align: center;">{{title}}</h2>
<hr>
<div class="card">
<div class="card-body">
<router-outlet></router-outlet>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<span>All Rights Reserved 2019 @JavaGuides</span>
</div>
</footer>
App Module
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { CreateEmployeeComponent } from './create-employee/create-employee.component'; import { EmployeeDetailsComponent } from './employee-details/employee-details.component'; import { EmployeeListComponent } from './employee-list/employee-list.component'; import { HttpClientModule } from '@angular/common/http'; import { UpdateEmployeeComponent } from './update-employee/update-employee.component'; @NgModule({ declarations: [ AppComponent, CreateEmployeeComponent, EmployeeDetailsComponent, EmployeeListComponent, UpdateEmployeeComponent ], imports: [ BrowserModule, AppRoutingModule, FormsModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Main Index Html File
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular8SpringbootClient</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
Main (Bootstrap) File
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Polyfills
import 'core-js/features/reflect';
import 'zone.js/dist/zone';
TypeScript tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "esnext",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}
Running Angular 8 App
ng serve
ng serve --port 4201
Demo
Add Employee Page
Delete Employee
Download Source Code
The source code of this tutorial available on my GitHub repository at https://github.com/RameshMF/Angular8-SpringBoot-CRUD-Tutorial/tree/master/angular8-springboot-client
All Angular 8 tutorials at https://www.javaguides.net/p/angular-8-tutorial-with-examples.html
problem refreshing list employees after adding
ReplyDeleteAfter adding employee, we made a call employees API to get all employees from database and that shown on employee list page. You can customize it as per your requirement.
DeleteThe problem is update and no create. Since EmployeeService methods are asynchronous. We turn to the page before actually having a crete or update. Use the gotoList method within the subscriber. So when you go back to the page, the update and create will actually be effective:
DeleteExemple create:
save() {
this.employeeService.createEmployee(this.employee).subscribe(
data => {
console.log(data);
this.gotoList(); //<-------------
}, error => console.log(error)
);
this.employee = new Employee();
//this.gotoList();
}
do you a tutorial for the api part?
ReplyDeleteThe rest api's reference given at start of this tutorial. Spring boot rest api's exposed at https://www.javaguides.net/2018/09/spring-boot-2-jpa-mysql-crud-example.html
Deleteusing slim 4
ReplyDeleteWhere is api part of this tutorial?
ReplyDeleteThe rest api's reference given at start of this tutorial. Spring boot rest api's exposed at https://www.javaguides.net/2018/09/spring-boot-2-jpa-mysql-crud-example.html
Deletehello m facing issue while update like when i tried to update the form without any changes then value goes null or undefined
ReplyDeletei am not able to update the employee list once it is added.i followed all the procedure as it is mentioned. please help me...
ReplyDeletehow to initialize the initial EmployeesListdata to display using createdb() method??
ReplyDeletenice one
Deleteupdate 2 items in my database and save changes. (I don't want to update all items in the table). I would be very grateful
ReplyDelete