I trying in the following way a custom validation so that when a duplicate name is put in the input to the array of objects defined in the ts, the message that the name already exists in the mat-error should appear
This is my html where I implement the form with the name field, where there are 2 mat errors, one indicating that it is required and the other indicating that the name already exists, I would greatly appreciate your help
app.html
<form [formGroup]="form">
<div>
<mat-form-field>
<input
matInput
type="text"
[formControl]="name"
required
/>
<mat-error *ngIf="name.hasError('required')">
It´s required
</mat-error>
<mat-error *ngIf="name.hasError('validateName')">
the name already exists
</mat-error>
</mat-form-field>
</div>
</form>
This is the ts where I initialize the form and put the validations
app.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, AbstractControl, ValidationErrors } from '@angular/forms';
@Component({
selector: 'app-formulario',
templateUrl: './component.html',
styleUrls: ['./component.scss'],
})
export class AdminMaintainerFormsDialogComponent implements OnInit{
public form: FormGroup;
public name: AbstractControl;
public totalStudents: any =
[
{
name: "Sandro",
rol: "student"
},
{
name: "Paola",
rol: "student"
}
];
constructor( private fb: FormBuilder) { }
ngOnInit() {
this.start();
}
start() {
this.form = this.fb.group({
name: ['', Validators.compose([Validators.required, this.validateName ])]
});
}
private validateName(control: AbstractControl): ValidationErrors | null {
const names = this.totalStudents;
let compareName;
names.map(value => {
compareName = value.name;
})
return compareName.test(control.value) ? null : {
validateName: {
valid: false
}
};
}
}
I believe that you are unable to retrieve totalStudents
value in the validateName
method.
You need to implement a ValidatorFn
method to pass the totalStudents
.
uniqueNameValidation(names: string[]): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
return !names.find((x) => x == control.value)
? null
: {
validateName: {
valid: false,
},
};
};
}
For the Form Group, pass the totalStudents
by mapping with name
only.
this.form = this.fb.group({
name: [
'',
Validators.compose([
Validators.required,
this.uniqueNameValidation(this.totalStudents.map((x) => x.name)),
]),
],
});
Side note:
Validators.compose([
Validators.required,
this.uniqueNameValidation(this.totalStudents.map((x) => x.name)),
]),
can be replaced with:
[
Validators.required,
this.uniqueNameValidation(this.totalStudents.map((x) => x.name)),
]
References