Building an application Company with Spring boot and Angular Part 3
Angular 10 Front-end
We will continue to complete this project with add and display Company, Department, Employee and Project
Components
The @Component decorator identifies the class immediately below it as a component class, and specifies its metadata. In the example code below, you can see that Component is just a class, with no special Angular notation or syntax at all. It's not a component until you mark it as one with the @Component decorator.
The metadata for a component tells Angular where to get the major building blocks that it needs to create and present the component and its view. In particular, it associates a template with the component, either directly with inline code, or by reference. Together, the component and its template describe a view.
In addition to containing or pointing to the template, the @Component metadata configures, for example, how the component can be referenced in HTML and what services it requires.
- add-company.component.html
src/app/add-company.component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { Company } from '../modal/Modal';
import { CompanyService } from '../service/company.service';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
@Component({
selector: 'app-add-company',
templateUrl: './add-company.component.html',
styleUrls: ['./add-company.component.css']
})
export class AddCompanyComponent implements OnInit {
company: Company = {} as Company;
progressBar = false;
constructor(private companyService: CompanyService, @Inject(MAT_DIALOG_DATA) public data: any) { }
ngOnInit(): void {
if(this.data.idCompany!=null) {
this.companyService.findCompany(this.data.idCompany).subscribe(company => {
this.company = company;
})
}
}
addCompany() {
this.showProgressBar = true;
if(this.data.idCompany!=null) {
this.companyService.editCompany(this.company, this.data.idCompany).subscribe(company => {
this.company = company;
window.location.reload();
})
} else {
this.companyService.addCompany(this.company, this.data.idUser).subscribe(company => {
this.company = company;
window.location.reload();
})
}
}
}
src/app/add-company.component.html
<div style="margin: auto; width: 100%; border: 3px solid #3f51b5;">
<mat-card>
<mat-card-header>
<mat-card-title>Add company</mat-card-title>
</mat-card-header>
<mat-card-content><br><br>
<mat-progress-bar mode="buffer" *ngIf="progressBar"></mat-progress-bar>
<form>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter name</mat-label>
<input matInput type="text" placeholder="Name" name="name" [(ngModel)]="company.name" #name="ngModel" required>
</mat-form-field><br>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter location</mat-label>
<input matInput type="text" placeholder="Location" name="location" [(ngModel)]="company.location" #location="ngModel" required>
</mat-form-field><br>
<mat-form-field style="width: 100%;">
<mat-label>Enter description</mat-label>
<textarea matInput placeholder="Description" name="description" [(ngModel)]="company.description" #description="ngModel"></textarea>
</mat-form-field><br>
<button mat-raised-button color="primary" [disabled]="name.invalid || location.invalid || description.invalid" (click)="addCompany()" style="width: 10em !important">Save</button>
</form>
</mat-card-content>
</mat-card>
</div>
src/app/display-company.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Company } from '../modal/Modal';
import { CompanyService } from '../service/company.service';
import { MatDialog } from '@angular/material/dialog';
import { AddCompanyComponent } from '../add-company/add-company.component';
import { AddDepartmentComponent } from '../add-department/add-department.component';
@Component({
selector: 'app-display-company',
templateUrl: './display-company.component.html',
styleUrls: ['./display-company.component.css']
})
export class DisplayCompanyComponent implements OnInit {
company: Company = {} as Company;
id: number;
constructor(private companyService: CompanyService, private route: ActivatedRoute,
private dialog: MatDialog) {
this.route.params.subscribe(
params => {
this.id = this.route.snapshot.params.id;
this.companyService.findCompany(this.id).subscribe(company => {
this.company = company;
})
}
)
}
ngOnInit(): void { }
editCompany(idCompany) {
this.dialog.open(AddCompanyComponent, {
data: {idCompany},
height: '400px',
width: '400px',
})
}
deleteCompany(idCompany) {
if(confirm('Are you sure')) {
this.companyService.deleteCompany(idCompany).subscribe(() => {
window.location.replace(`/dashbaord`);
})
}
}
addDepartment(idCompany) {
this.dialog.open(AddDepartmentComponent, {
data: {idCompany},
height: '400px',
width: '400px',
})
}
}
src/app/display-company.component.html
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>Company: {{company.name}}</mat-card-title>
<mat-card-subtitle>Location: {{company.location}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p style="background: #f5f6fa; padding: 15px;border-radius: 6px; color: rgba(0,0,0,.54);">
{{company.description}}
</p>
<hr>
</mat-card-content>
<mat-card-actions>
<button mat-button color="primary" (click)="addDepartment(company.id)">Add department</button>
<button mat-button color="accent" (click)="editCompany(company.id)">Update</button>
<button mat-button color="warn" (click)="deleteCompany(company.id)">Delete</button>
<button mat-button disabled>{{company.createAt|date}}</button>
</mat-card-actions>
</mat-card>
src/app/add-department.component.ts
import { Component, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Department } from '../modal/Modal';
import { DepartmentService } from '../service/department.service';
@Component({
selector: 'app-add-department',
templateUrl: './add-department.component.html',
styleUrls: ['./add-department.component.css']
})
export class AddDepartmentComponent implements OnInit {
department: Department = {} as Department;
progressBar = false;
constructor(@Inject(MAT_DIALOG_DATA) public data: any, private departmentService: DepartmentService) { }
ngOnInit(): void {
if(this.data.idDepartment!=null) {
this.departmentService.findDepartment(this.data.idDepartment).subscribe(department => {
this.department = department;
})
}
}
addDeprtmant() {
this.showProgressBar = true;
if(this.data.idDepartment!=null) {
this.departmentService.editDepartment(this.department, this.data.idDepartment).subscribe(department => {
this.department = department;
window.location.reload();
})
} else {
this.departmentService.addDepartment(this.department , this.data.idCompany).subscribe(department => {
this.department = department;
window.location.reload();
})
}
}
}
src/app/add-department.component.html
<div style="margin: auto; width: 100%; border: 3px solid #3f51b5;">
<mat-card>
<mat-card-header>
<mat-card-title>Add department</mat-card-title>
</mat-card-header>
<mat-card-content><br><br>
<mat-progress-bar mode="buffer" *ngIf="progressBar"></mat-progress-bar>
<form>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter code</mat-label>
<input matInput type="text" placeholder="Code" name="code" [(ngModel)]="department.code" #code="ngModel" required>
</mat-form-field><br>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter location</mat-label>
<input matInput type="text" placeholder="Location" name="location" [(ngModel)]="department.location" #location="ngModel" required>
</mat-form-field><br>
<mat-form-field style="width: 100%;">
<mat-label>Enter description</mat-label>
<textarea matInput placeholder="Description" name="description" [(ngModel)]="department.description" #description="ngModel"></textarea>
</mat-form-field><br>
<button mat-raised-button color="primary" [disabled]="code.invalid || location.invalid || description.invalid" (click)="addDeprtmant()" style="width: 10em !important">Save</button>
</form>
</mat-card-content>
</mat-card>
</div>
src/app/display-department.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Department } from '../modal/Modal';
import { DepartmentService } from '../service/department.service';
import { MatDialog } from '@angular/material/dialog';
import { AddEmployeeComponent } from '../add-employee/add-employee.component';
import { AddDepartmentComponent} from '../add-department/add-department.component';
import { AddProjectToDeprtmentComponent } from './add-project-to-deprtment/add-project-to-deprtment.component';
@Component({
selector: 'app-display-department',
templateUrl: './display-department.component.html',
styleUrls: ['./display-department.component.css']
})
export class DisplayDepartmenntComponent implements OnInit {
department: Department = {} as Department;
idDepartment: number;
constructor(private route: ActivatedRoute, private departmentService: DepartmentService,
private dialog: MatDialog) { }
ngOnInit(): void {
this.idDepartment = this.route.snapshot.params.id;
this.departmentService.findDepartment(this.idDepartment).subscribe(department => {
this.department = department;
})
}
addEmployee(idDepartment) {
this.dialog.open(AddEmployeeComponent, {
data: {idDepartment},
height: '540px',
width: '400px',
})
}
editDepartment(idDepartment) {
this.dialog.open(AddDepartmentComponent, {
data: {idDepartment},
height: '400px',
width: '400px',
})
}
addProject(idDepartment) {
this.dialog.open(AddProjectToDeprtmentComponent, {
data: {idDepartment},
height: '400px',
width: '400px',
})
}
deleteDepartment(idDepartment) {
if(confirm('Are you sure')) {
this.departmentService.deleteDepartment(idDepartment).subscribe(() => {
window.location.replace(`/dashbaord`);
})
}
}
}
src/app/display-department.component.html
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>Department: {{department.code}}</mat-card-title>
<mat-card-subtitle>Location: {{department.location}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p style="background: #f5f6fa; padding: 15px;border-radius: 6px; color: rgba(0,0,0,.54);">
{{department.description}}
</p>
<hr>
<mat-list>
<div mat-subheader>Projects</div>
<mat-list-item *ngFor="let pro of department.projects">
<mat-icon mat-list-icon>folder</mat-icon>
<div mat-line>{{pro.name}}</div>
<div mat-line> {{pro.createAt | date}} </div>
<button mat-raised-button color="primary" [routerLink]="['/dashbaord/display-department/' + department.id + '/display-project/', pro.id]" >Project details</button>
</mat-list-item>
<mat-divider></mat-divider>
</mat-list>
</mat-card-content>
<mat-card-actions>
<button mat-button color="primary" (click)="addEmployee(department.id)">Add employee</button>
<button mat-button color="primary" (click)="addProject(department.id)">Add project</button>
<button mat-button color="accent" (click)="editDepartment(department.id)">Update department</button>
<button mat-button color="warn" (click)="deleteDepartment(department.id)">Delete department</button>
<button mat-button disabled>{{company.createAt|date}}</button>
<button mat-button disabled>{{department.createAt|date}}</button>
</mat-card-actions>
</mat-card>
<div style="margin-top: 15px; margin-bottom: 40px;">
<router-outlet></router-outlet>
</div>
src/app/add-employee.component.ts
import { Component, OnInit, Inject } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Employee } from '../modal/Modal';
import { EmployeeService } from '../service/employee.service';
@Component({
selector: 'app-add-employee',
templateUrl: './add-employee.component.html',
styleUrls: ['./add-employee.component.css']
})
export class AddEmployeeComponent implements OnInit {
employee: Employee = {} as Employee;
progressBar = false;
constructor(@Inject@Inject(MAT_DIALOG_DATA) public data: any, private employeeService: EmployeeService) { }
ngOnInit(): void {
if(this.data.idEmployee!=null) {
this.employeeService.findEmployee(this.data.idEmployee).subscribe(employee => {
this.employee = employee;
})
}
}
addEmployee() {
this.showProgressBar = true;
if(this.data.idEmployee!=null) {
this.employeeService.editEmployee(this.employee, this.data.idEmployee).subscribe(employee => {
this.employee = employee;
window.location.reload();
})
} else {
this.employeeService.addEmployee(this.employee, this.data.idDepartment).subscribe(employee => {
this.employee = employee;
window.location.reload();
})
}
}
}
src/app/add-employee.component.html
<div style="margin: auto; width: 100%; border: 3px solid #3f51b5;">
<mat-card>
<mat-card-header>
<mat-card-title>Add employee</mat-card-title>
</mat-card-header>
<mat-card-content><br><br>
<mat-progress-bar mode="buffer" *ngIf="progressBar"></mat-progress-bar>
<form>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter name</mat-label>
<input matInput type="text" placeholder="Name" name="name" [(ngModel)]="employee.name" #name="ngModel" required>
</mat-form-field><br>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter address</mat-label>
<input matInput type="text" placeholder="Address" name="address" [(ngModel)]="employee.address" #address="ngModel" required>
</mat-form-field><br>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter birth date</mat-label>
<input matInput type="text" placeholder="Birth date" name="birthDate" [(ngModel)]="employee.birthDate" #birthDate="ngModel" required>
</mat-form-field><br>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter hiring date</mat-label>
<input matInput type="text" placeholder="Hiring date" name="hiringDate" [(ngModel)]="employee.hiringDate" #hiringDate="ngModel" required>
</mat-form-field><br>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter salary</mat-label>
<input matInput type="number" placeholder="Salary" name="salary" [(ngModel)]="employee.salary" #salary="ngModel" required>
</mat-form-field><br>
<button mat-raised-button color="primary" [disabled]="name.invalid || salary.invalid || address.invalid || birthDate.invalid || hiringDate.invalid" (click)="addEmployee()" style="width: 10em !important">Save</button>
</form>
</mat-card-content>
</mat-card>
</div>
src/app/display-employee.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute} from '@angular/router';
import { Employee, EmployeePhone, Project} from '../modal/Modal';
import { EmployeeService } from '../service/employee.service';
import { MatDialog } from '@angular/material/dialog';
import { AddEmployeeComponent } from '../add-employee/add-employee.component';
import { AddProjectToEmployeComponent } from '../add-project-to-employe/add-project-to-employe.component';
import { AddEmployeePhoneComponent } from '../add-employee-phone/add-employee-phone.component';
import { EmployeePhoneService } from '../service/employee-phone.service';
import { ProjectService } from '../service/project.service';
@Component({
selector: 'app-display-employee',
templateUrl: './display-employee.component.html',
styleUrls: ['./display-employee.component.css']
})
export class DisplayEmployeeComponent implements OnInit {
employeePhones: EmployeePhone[];
projects: Project[];
employee: Employee = {} as Employee;
idEmployee: number;
constructor(private employeeService: EmployeeService, private route: ActivatedRoute,
private dialog: MatDialog, private employeePhoneService: EmployeePhoneService,
private projectService: ProjectService) {
this.route.params.subscribe(
params => {
this.idEmployee = this.route.snapshot.params.id;
this.projectService.findProjectsForEmplopyee(this.idEmployee).subscribe(projects => {
this.projects = projects;
});
this.employeeService.findEmployee(this.idEmployee).subscribe(employee => {
this.employee = employee;
this.employeePhoneService.findEmployeePhones(this.idEmployee).subscribe(employeePhones => {
this.employeePhones = employeePhones;
})
})
}
)
}
deleteEmployee(idEmployee) {
if(confirm('Are you sure')) {
this.employeeService.deleteEmployee(idEmployee).subscribe(() => {
window.location.replace(`/dashbaord`);
})
}
}
editEmployee(idEmployee) {
this.dialog.open(AddEmployeeComponent, {
data: {idEmployee},
height: '540px',
width: '400px',
})
}
addProjectToEmployee(idEmployee) {
this.dialog.open(AddProjectToEmployeComponent, {
data: {idEmployee},
height: '220px',
width: '400px',
})
}
addPhone(idEmployee) {
this.dialog.open(AddEmployeePhoneComponent, {
data: {idEmployee},
height: '250px',
width: '400px',
})
}
editPhoone(idPhone) {
this.dialog.open(AddEmployeePhoneComponent, {
data: {idPhone},
height: '250px',
width: '400px',
})
}
deletePhoone(idPhone) {
if(confirm('Are you sure')) {
this.employeePhoneService.deleteEmployeePhone(idPhone).subscribe(() => {
window.location.reload();
})
}
}
deleteProjectFromEmployee(idEmployee, idProject) {
if(confirm('Are you sure')){
this.projectService.deleteProjectFromEmployee(idEmployee, idProject).subscribe(() => {
window.location.reload();
})
}
}
}
src/app/display-employee.component.html
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>Name: {{employee.name}}</mat-card-title>
<mat-card-subtitle>Address: {{employee.address}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<hr>
<div style="background: #f5f6fa; padding: 15px;border-radius: 6px;">
<mat-list role="list">
<mat-list-item role="listitem">Birth date: {{employee.birthDate}}</mat-list-item>
<mat-list-item role="listitem">Hiring date: {{employee.hiringDate}}</mat-list-item>
<mat-list-item role="listitem" color="accent">Salary: {{employee.salary}}</mat-list-item>
</mat-list>
</div>
<hr>
<div style="background-color: #ecf0f1; padding: 15px;border-radius: 6px;">
<mat-list>
<div mat-subheader>Phones</div>
<mat-list-item *ngFor="let phone of employeePhones">
<mat-icon mat-list-icon>phone</mat-icon>
<div mat-line>{{phone.phone}} </div>
<i class="fas fa-edit" style="cursor: pointer; color: cadetblue; margin-right: 15px;" (click)="editPhoone(phone.id)"></i>
<i class="fas fa-trash-alt" style="cursor: pointer; color: #c0392b;" (click)="deletePhoone(phone.id)"></i>
</mat-list-item>
</mat-list>
</div>
<hr>
<div style="background-color: #dcdde1; padding: 15px;border-radius: 6px; color: rgba(0,0,0,.54);">
<mat-list>
<div mat-subheader>Projects</div>
<mat-list-item *ngFor="let pro of projects">
<mat-icon mat-list-icon>model_training</mat-icon>
<div mat-line>{{pro.name}}</div>
<i class="fas fa-eye-slash" style="cursor: pointer; color: #8e44ad; margin-right: 15px;"
[routerLink]="['/dashbaord/display-project-employee/', pro.id]"></i>
<i class="fas fa-trash-alt" style="cursor: pointer; color: #c0392b;"
(click)="deleteProjectFromEmployee(employee.id, pro.id)"></i>
</mat-list-item>
</mat-list>
</div>
</mat-card-content>
<mat-card-actions>
<button mat-button color="primary" (click)="addProjectToEmployee(employee.id)">Add project</button>
<button mat-button color="primary" (click)="addPhone(employee.id)">Add phone</button>
<button mat-button color="accent" (click)="editEmployee(employee.id)">Update employee</button>
<button mat-button color="warn" (click)="deleteEmployee(employee.id)">Delete employee</button>
<button mat-button disabled>{{company.createAt|date}}</button>
</mat-card-actions>
</mat-card>
src/app/add-employee-phone.component.ts
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { EmployeePhone } from '../modal/Modal';
import { EmployeePhoneService } from '../service/employee-phone.service';
@Component({
selector: 'app-add-employee-phone',
templateUrl: './add-employee-phone.component.html',
styleUrls: ['./add-employee-phone.component.css']
})
export class AddEmployeePhoneComponent implements OnInit {
employeePhone: EmployeePhone = {} as EmployeePhone;
progressBar = false;
constructor(@Inject(MAT_DIALOG_DATA) public data: any, private employeePhoneService: EmployeePhoneService) { }
ngOnInit(): void {
if(this.data.idPhone!=null) {
this.employeePhoneService.findEmployeePhone(this.data.idPhone).subscribe(employeePhone => {
this.employeePhone = employeePhone;
})
}
}
addPhone() {
this.showProgressBar = true;
if(this.data.idPhone!=null) {
this.employeePhoneService.editEmployeePhone(this.employeePhone, this.data.idPhone).subscribe(employeePhone => {
this.employeePhone = employeePhone;
window.location.reload();
})
} else {
this.employeePhoneService.addEmployeePhone(this.employeePhone, this.data.idEmployee).subscribe(employeePhone => {
this.employeePhone = employeePhone;
window.location.reload();
})
}
}
}
src/app/add-employee-phone.component.html
<div style="margin: auto; width: 100%; border: 3px solid #3f51b5;">
<mat-card>
<mat-card-header>
<mat-card-title>Add employee phone</mat-card-title>
</mat-card-header>
<mat-card-content><br><br>
<mat-progress-bar mode="buffer" *ngIf="progressBar"></mat-progress-bar>
<form>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter phone</mat-label>
<input matInput type="number" placeholder="Phone" name="code" [(ngModel)]="employeePhone.phone" #phone="ngModel" required>
</mat-form-field><br>
<button mat-raised-button color="primary" [disabled]="phone.invalid" (click)="addPhone()" style="width: 10em !important">Save</button>
</form>
</mat-card-content>
</mat-card>
</div>
src/app/display-employee-phone.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Project } from '../modal/Modal';
import { ProjectService } from '../service/project.service';
import { MatDialog } from '@angular/material/dialog';
import { AddProjectToDeprtmentComponent } from '../add-project-to-deprtment/add-project-to-deprtment.component';
@Component({
selector: 'app-display-project-employee',
templateUrl: './display-project-employee.component.html',
styleUrls: ['./display-project-employee.component.css']
})
export class DisplayProjectEmployeeComponent implements OnInit {
project: Project = {} as Project;
id: number;
constructor(private projectService: ProjectService, private route: ActivatedRoute,
private dialog: MatDialog) {
this.route.params.subscribe(
params => {
this.id = this.route.snapshot.params.id;
this.projectService.findProject(this.id).subscribe(project => {
this.project = project;
})
}
)
}
ngOnInit(): void { }
deleteProject(id) {
if(confirm('Are you sure')){
this.projectService.deleteProejct(id).subscribe(() => {
window.location.replace(`/dashbaord`);
});
}
}
editProject(idProject) {
this.dialog.open(AddProjectToDeprtmentComponent, {
data: {idProject},
height: '480px',
width: '400px',
})
}
}
src/app/display-employee-phone.component.html
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>{{project.name}}</mat-card-title>
<mat-card-subtitle>{{project.createAt|date}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p style="background: #f5f6fa; padding: 15px;border-radius: 6px; color: rgba(0,0,0,.54);">
{{project.description}}
</p>
<hr>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" *ngIf="project.process==['TODO']">{{project.process}}</button>
<button mat-raised-button color="accent" *ngIf="project.process==['WORKON']">{{project.process}}</button>
<button mat-raised-button color="warn" *ngIf="project.process==['DONE']">{{project.process}}</button>
<button mat-button color="primary" (click)="editProject(project.id)">Edit project</button>
<button mat-button color="accent" (click)="deleteProject(project.id)">Delete project</button>
</mat-card-actions>
</mat-card>
src/app/add-project-to-deprtment.component.ts
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Project } from '../modal/Modal';
import { ProjectService } from '../service/project.service';
@Component({
selector: 'app-add-project-to-deprtment',
templateUrl: './add-project-to-deprtment.component.html',
styleUrls: ['./add-project-to-deprtment.component.css']
})
export class AddProjectToDeprtmentComponent implements OnInit {
process: any = {};
project: Project = {} as Project;
progressBar = false;
constructor(@Inject(MAT_DIALOG_DATA) public data: any, private projectService: ProjectService) { }
ngOnInit(): void {
if(this.data.idProject!=null) {
this. projectService.findProject(this.data.idProject).subscribe(project => {
this.project = project
})
}
}
setProcess(e) {
this.process = e;
}
addProject() {
this.showProgressBar = true;
this.project.process = this.process;
if(this.data.idProject!=null) {
this.projectService.editProject(this.project, this.data.idProject).subscribe(project => {
this.project = project;
window.location.reload();
})
} else {
this.projectService.addProjectToDeprtment(this.project, this.data.idDepartment).subscribe(project => {
this.project = project;
window.location.reload();
})
}
}
}
src/app/add-project-to-deprtment.component.html
<div style="margin: auto; width: 100%; border: 3px solid #3f51b5;">
<mat-card>
<mat-card-header>
<mat-card-title>Add project to department</mat-card-title>
</mat-card-header>
<mat-card-content><br><br>
<mat-progress-bar mode="buffer" *ngIf="progressBar"></mat-progress-bar>
<form>
<mat-form-field appearance="fill" style="width: 100%;">
<mat-label>Enter name</mat-label>
<input matInput type="text" placeholder="Name" name="name" [(ngModel)]="project.name" #name="ngModel" required>
</mat-form-field><br>
<mat-label>Enter description</mat-label>
<textarea matInput placeholder="Description" name="description" [(ngModel)]="project.description" #description="ngModel"></textarea>
</mat-form-field><br>
<label style="font-weight: bold;">Process</label><br><br>
<mat-radio-group name="process" [(ngModel)]="process" (ngModelChange)="setProcess($event)">
<mat-radio-button [checked]="project.process==['TODO']" [value]="'TODO'"> To do </mat-radio-button><br>
<mat-radio-button [checked]="project.process==['WORKON']" [value]="'WORKON'" style="margin: 10px 0"> Workon</mat-radio-button><br>
<mat-radio-button [checked]="project.process==['DONE']" [value]="'DONE'"> Done </mat-radio-button><br>
</mat-radio-group><br>
<button mat-raised-button color="primary" [disabled]="name.invalid || description.invalid" (click)="addCompany()" style="width: 10em !important">Save</button>
</form>
</mat-card-content>
</mat-card>
</div>
src/app/display-project.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Project } from '../modal/Modal';
import { ProjectService } from '../service/project.service';
import { MatDialog } from '@angular/material/dialog';
import { AddProjectToDeprtmentComponent } from '../add-project-to-deprtment/add-project-to-deprtment.component';
@Component({
selector: 'app-display-project',
templateUrl: './display-project.component.html',
styleUrls: ['./display-project.component.css']
})
export class HomeComponent implements OnInit {
project: Project = {} as Project;
id: number;
constructor(private projectService: ProjectService, private route: ActivatedRoute,
private dialog: MatDialog) {
this.route.params.subscribe(
params => {
this.id = this.route.snapshot.params.id;
this.projectService.findProject(this.id).subscribe(project => {
this.project = project;
})
}
)
}
ngOnInit(): void { }
deleteProject(id) {
if(confirm('Are you sure')){
this.projectService.deleteProejct(id).subscribe(() => {
window.location.replace(`/dashbaord`);
});
}
}
editProject(idProject) {
this.dialog.open(AddProjectToDeprtmentComponent, {
data: {idProject},
height: '480px',
width: '400px',
})
}
}
src/app/display-project.component.html
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>{{project.name}}</mat-card-title>
<mat-card-subtitle>{{project.createAt|date}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p style="background: #f5f6fa; padding: 15px;border-radius: 6px; color: rgba(0,0,0,.54);">
{{project.description}}
</p>
<hr>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" *ngIf="project.process==['TODO']">{{project.process}}</button>
<button mat-raised-button color="accent" *ngIf="project.process==['WORKON']">{{project.process}}</button>
<button mat-raised-button color="warn" *ngIf="project.process==['DONE']">{{project.process}}</button>
<button mat-button color="primary" (click)="editProject(project.id)">Edit project</button>
<button mat-button color="accent" (click)="deleteProject(project.id)">Delete project</button>
</mat-card-actions>
</mat-card>
src/app/add-project-to-employee.component.ts
import { Component, Inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Project } from '../modal/Modal';
import { ProjectService } from '../service/project.service';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
@Component({
selector: 'app-add-project-to-employe',
templateUrl: './add-project-to-employe.component.html',
styleUrls: ['./add-project-to-employe.component.css']
})
export class AddProjectToEmployeComponent implements OnInit {
projects: Project[];
progressBar = false;
constructor(private projectService: ProjectService, @Inject(MAT_DIALOG_DATA) public data: any,
private route: ActivatedRoute) {
this.route.params.subscribe(
params => {
this.projectService.findProjects().subscribe(projects => {
this.projects = projects;
this.projectService.findProjectsForEmplopyee(this.data.idEmployee).subscribe(filterProjects => {
filterProjects.forEach(pro => {
this.projects = this.projects.filter(p => p.id !== pro.id);
})
})
})
}
)
}
ngOnInit(): void { }
AddProjectToEmployee(e) {
this.projectService.addProjectToEmployee(this.data.idEmployee, e.value).forEach(() => {
window.location.replace(`/dashbaord`);
})
}
}
src/app/add-project-to-employee.component.html
<div style="margin: auto; width: 100%; border: 3px solid #3f51b5;">
<mat-card>
<mat-card-header>
<mat-card-title>Add project to employee</mat-card-title>
</mat-card-header>
<mat-card-content><br><br>
<mat-progress-bar mode="buffer" *ngIf="progressBar"></mat-progress-bar>
<form>
<mat-form-field style="width: 100%;">
<mat-label>Choose a project</mat-label>
<mat-select (selectionChange)="AddProjectToEmployee($event)">
<mat-option *ngFor="let pro of projects" [value]="pro.id">{{pro.name}}</mat-option>
</mat-select>
</mat-form-field>
</form>
</mat-card-content>
</mat-card>
</div>
Add the AppRoutingModule
In Angular, the best practice is to load and configure the router in a separate, top-level module that is dedicated to routing and imported by the root AppModule.
By convention, the module class name is AppRoutingModule and it belongs in the app-routing.module.ts in the src/app folder.
app-routing-module.ts
src/app/app-routing.module.ts
import { LoginComponent } from './login/login.component';
import { DashboardComponent} from './dashboard/dashboard.component';
import { NgModule } from '@angular/core';
import { DisplayCompanyComponent } from './display-company/display-company.component';
import { Routes, RouterModule } from '@angular/router';
import { DisplayDepartmenntComponent } from './display-departmennt/display-departmennt.component';
import { DisplayEmployeeComponent } from './display-employee/display-employee.component';
import { DisplayProjectComponent } from './display-project/display-project.component';
import { DisplayProjectEmployeeComponent } from './display-project-employee/display-project-employee.component';
const routes: Routes = [
{ path: '', redirectTo: '/login', pathMatch: 'full' },
{
path: 'login',
component: LoginComponent
},
{
path: 'dashbaord',
component: DashboardComponent,
children: [
{
path: 'display-company/:id',
component: DisplayCompanyComponent
},
{
path: 'display-department/:id',
component: DisplayDepartmenntComponent,
children: [
{
path: 'display-project/:id',
component: DisplayProjectComponent
}
]
},
{
path: 'display-employee/:id',
component: DisplayEmployeeComponent
},
{
path: 'display-project-employee/:id',
component: DisplayProjectEmployeeComponent
}
]
},
];
@NgModule({
declarations: [],
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
NgModules and JavaScript modules
The NgModule system is different from and unrelated to the JavaScript (ES2015) module system for managing collections of JavaScript objects. These are complementary module systems that you can use together to write your apps.
In JavaScript each file is a module and all objects defined in the file belong to that module. The module declares some objects to be public by marking them with the export key word. Other JavaScript modules use import statements to access public objects from other modules.
app-module.ts
src/app/app-module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { FormsModule } from '@angular/forms';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from './material-module';
import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { AddCompanyComponent } from './add-company/add-company.component';
import { DisplayCompanyComponent } from './display-company/display-company.component';
import { AddDepartmentComponent } from './add-department/add-department.component';
import { DisplayDepartmenntComponent } from './display-departmennt/display-departmennt.component';
import { AddEmployeeComponent } from './add-employee/add-employee.component';
import { DisplayEmployeeComponent } from './display-employee/display-employee.component';
import { AddProjectToDeprtmentComponent } from './add-project-to-deprtment/add-project-to-deprtment.component';
import { DisplayProjectComponent } from './display-project/display-project.component';
import { AddProjectToEmployeComponent } from './add-project-to-employe/add-project-to-employe.component';
import { DisplayProjectEmployeeComponent } from './display-project-employee/display-project-employee.component';
import { AddEmployeePhoneComponent } from './add-employee-phone/add-employee-phone.component';
import { DatePipe } from '@angular/common';
@NgModule({
declarations: [
AppComponent,
AppComponent,
LoginComponent,
DashboardComponent,
AddCompanyComponent,
DisplayCompanyComponent,
AddDepartmentComponent,
DisplayDepartmenntComponent,
AddEmployeeComponent,
DisplayEmployeeComponent,
AddProjectToDeprtmentComponent,
DisplayProjectComponent,
AddProjectToEmployeComponent,
DisplayProjectEmployeeComponent,
AddEmployeePhoneComponent
],
imports: [
BrowserModule,
HttpClientModule,
FormsModule,
NoopAnimationsModule,
MaterialModule,
AppRoutingModule
],
providers: [DatePipe],
bootstrap: [AppComponent],
schemas: [ CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA ]
})
export class AppModule { }
Conclusion
Now we have an overview of Angular 10 + Spring Boot App.
We also take a look at client-server architecture for REST API using Spring Web MVC & Spring Data JPA, as well as Angular 10 project structure for building a front-end app to make HTTP requests and consume responses.