add errors to employee creation form #33

Merged
csimonis merged 1 commits from feature/create-employee-errors into main 2025-01-15 08:27:46 +00:00
2 changed files with 62 additions and 21 deletions

View File

@ -6,34 +6,40 @@
<mat-form-field class="!w-full"> <mat-form-field class="!w-full">
<mat-label>First Name</mat-label> <mat-label>First Name</mat-label>
<input matInput formControlName="firstName" required> <input matInput formControlName="firstName" required>
<mat-error *ngIf="errors['firstName']">{{errors['firstName']}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="!w-full"> <mat-form-field class="!w-full">
<mat-label>Last Name</mat-label> <mat-label>Last Name</mat-label>
<input matInput formControlName="lastName" required> <input matInput formControlName="lastName" required>
<mat-error *ngIf="errors['lastName']">{{errors['lastName']}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<mat-form-field class="!w-full"> <mat-form-field class="!w-full">
<mat-label>Street</mat-label> <mat-label>Street</mat-label>
<input matInput formControlName="street" required> <input matInput formControlName="street" required>
<mat-error *ngIf="errors['street']">{{errors['street']}}</mat-error>
</mat-form-field> </mat-form-field>
<div class="flex gap-x-4"> <div class="flex gap-x-4">
<mat-form-field class="!w-full"> <mat-form-field class="!w-full">
<mat-label>City</mat-label> <mat-label>City</mat-label>
<input matInput formControlName="city" required> <input matInput formControlName="city" required>
<mat-error *ngIf="errors['city']">{{errors['city']}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="!w-1/2"> <mat-form-field class="!w-1/2">
<mat-label>Postcode</mat-label> <mat-label>Postcode</mat-label>
<input matInput formControlName="postcode" minlength="5" maxlength="5" type="number" required> <input matInput formControlName="postcode" minlength="5" maxlength="5" type="number" required>
<mat-error *ngIf="errors['postcode']">{{errors['postcode']}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<mat-form-field class="!w-full"> <mat-form-field class="!w-full">
<mat-label>Phone</mat-label> <mat-label>Phone</mat-label>
<input matInput formControlName="phone" required> <input matInput formControlName="phone" required>
<mat-error *ngIf="errors['phone']">{{errors['phone']}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="!w-full"> <mat-form-field class="!w-full">
@ -43,6 +49,7 @@
{{qualification.skill}} {{qualification.skill}}
</mat-option> </mat-option>
</mat-select> </mat-select>
<mat-error *ngIf="errors['qualifications']">{{errors['qualifications']}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-dialog-actions align="end"> <mat-dialog-actions align="end">

View File

@ -1,7 +1,7 @@
import {Component, inject, OnInit} from '@angular/core'; import {Component, inject, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms"; import {AbstractControl, FormBuilder, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms";
import {MatFormField, MatLabel} from "@angular/material/form-field"; import {MatFormField, MatLabel} from "@angular/material/form-field";
import {MatInput} from "@angular/material/input"; import {MatError, MatInput} from "@angular/material/input";
import {MatButton} from "@angular/material/button"; import {MatButton} from "@angular/material/button";
import { import {
MatDialogActions, MatDialogActions,
@ -17,6 +17,7 @@ import {MatOption} from "@angular/material/core";
import {MatSelect} from "@angular/material/select"; import {MatSelect} from "@angular/material/select";
import QualificationService from "../../services/qualification.service"; import QualificationService from "../../services/qualification.service";
import {Qualification} from "../../qualification/Qualification"; import {Qualification} from "../../qualification/Qualification";
import {debounceTime} from "rxjs";
@Component({ @Component({
selector: 'app-create-employee', selector: 'app-create-employee',
@ -34,18 +35,30 @@ import {Qualification} from "../../qualification/Qualification";
MatOption, MatOption,
MatSelect, MatSelect,
NgForOf, NgForOf,
MatError,
], ],
templateUrl: './create.component.html', templateUrl: './create.component.html',
standalone: true, standalone: true,
styleUrl: './create.component.css' styleUrl: './create.component.css'
}) })
export class CreateComponent implements OnInit { export class CreateComponent implements OnInit {
employeeForm: FormGroup | null = null; employeeForm!: FormGroup;
employeeService: EmployeeApiService = inject(EmployeeApiService); employeeService: EmployeeApiService = inject(EmployeeApiService);
formBuilder: FormBuilder = inject(FormBuilder); formBuilder: FormBuilder = inject(FormBuilder);
dialogRef: MatDialogRef<CreateComponent> = inject(MatDialogRef); dialogRef: MatDialogRef<CreateComponent> = inject(MatDialogRef);
qualificationService: QualificationService = inject(QualificationService); qualificationService: QualificationService = inject(QualificationService);
qualifications: Qualification[] = []; qualifications: Qualification[] = [];
errorMsgs: { [key: string]: string } = {
firstName: 'First name is required',
lastName: 'Last name is required',
street: 'Street is required',
postcode: 'Postcode must be 5 characters long',
city: 'City is required',
phone: 'Phone is required',
qualifications: 'Qualifications are required'
}
errors: { [key: string]: string } = {}
ngOnInit(): void { ngOnInit(): void {
this.loadQualifications(); this.loadQualifications();
@ -53,11 +66,18 @@ export class CreateComponent implements OnInit {
firstName: ['', Validators.required], firstName: ['', Validators.required],
lastName: ['', Validators.required], lastName: ['', Validators.required],
street: ['', Validators.required], street: ['', Validators.required],
postcode: ['', [Validators.required, Validators.minLength(5), Validators.maxLength(5)]], postcode: ['', [Validators.required, this.validatePostcode]],
city: ['', Validators.required], city: ['', Validators.required],
phone: ['', Validators.required], phone: ['', Validators.required],
qualifications: [[]] qualifications: [[]]
}); });
Object.keys(this.employeeForm.controls).forEach((controlName: string) => {
const control = this.employeeForm.controls[controlName];
control.valueChanges.pipe(debounceTime(10)).subscribe(() => {
this.showErrorMsg(controlName, control);
});
});
} }
loadQualifications() { loadQualifications() {
@ -67,8 +87,7 @@ export class CreateComponent implements OnInit {
} }
submit() { submit() {
if (this.employeeForm === null || !this.employeeForm.valid) { if (!this.employeeForm.valid) {
console.error('Form invalid');
return; return;
} }
@ -81,4 +100,19 @@ export class CreateComponent implements OnInit {
this.employeeService.create(employeeData as Employee).subscribe(); this.employeeService.create(employeeData as Employee).subscribe();
this.dialogRef.close(true); this.dialogRef.close(true);
} }
showErrorMsg(controlName: string, control: AbstractControl | undefined) {
if (control?.errors) {
this.errors[controlName] = this.errorMsgs[controlName];
}
}
validatePostcode(control: AbstractControl) {
const postcode = control.value as number;
if (postcode.toString().length !== 5) {
return {invalidPostcode: true};
}
return null;
}
} }