I implemented a confirm password validation in Angular with a custom validator. Here is the custom validator class:
import { AbstractControl, ValidatorFn } from '@angular/forms';
export class Validation {
static match(controlName: string, checkControlName: string): ValidatorFn {
return (controls: AbstractControl) => {
const control = controls.get(controlName);
const checkControl = controls.get(checkControlName);
if (checkControl?.errors && !checkControl.errors.matching) {
return null;
}
if (control?.value !== checkControl?.value) {
controls?.get(checkControlName)?.setErrors({ matching: true });
return { matching: true };
} else {
return null;
}
};
}
}
I use reactive form, this is how I build it up:
initSignupForm() {
this.signupForm = new FormGroup(
{
email: new FormControl(this.formData.email, [
Validators.required,
Validators.email,
]),
password: new FormControl(this.formData.password, [
Validators.required,
]),
passwordConfirm: new FormControl(this.formData.passwordConfirm, [
Validators.required,
]),
},
{ validators: [Validation.match('password', 'passwordConfirm')] }
);
}
And this is the component html:
<div class="card">
<kendo-card width="320px">
<h2>Regisztráció</h2>
<form [formGroup]="signupForm">
<kendo-formfield>
<kendo-textbox placeholder="E-mail cím" formControlName="email">
<ng-template kendoTextBoxPrefixTemplate>
<kendo-svg-icon [icon]="icons.user"></kendo-svg-icon>
<div id="empty-div"></div>
</ng-template>
</kendo-textbox>
<kendo-formerror *ngIf="signupForm.controls.email.errors?.required"
>Kötelező mező</kendo-formerror
>
<kendo-formerror *ngIf="signupForm.controls.email.errors?.email"
>Hibás e-mail formátum</kendo-formerror
>
</kendo-formfield>
<kendo-formfield>
<kendo-textbox
placeholder="Jelszó"
#tbxPassword
formControlName="password"
>
<ng-template kendoTextBoxPrefixTemplate>
<button
id="tbxPassword"
kendoButton
icon="eye"
(click)="togglePass()"
></button>
</ng-template>
</kendo-textbox>
<kendo-formerror>Kötelező mező</kendo-formerror>
</kendo-formfield>
<kendo-formfield>
<kendo-textbox
placeholder="Jelszó még egyszer"
#tbxRepeatPassword
formControlName="passwordConfirm"
>
<ng-template kendoTextBoxPrefixTemplate>
<button kendoButton icon="eye" (click)="togglePassRep()"></button>
</ng-template>
</kendo-textbox>
<kendo-formerror
*ngIf="signupForm.controls.passwordConfirm.errors?.required"
>Kötelező mező</kendo-formerror
>
<kendo-formerror *ngIf="signupForm.errors?.matching"
>A két jelszó nem egyezik</kendo-formerror
>
</kendo-formfield>
<button class="btn" kendoButton [primary]="true" (click)="submitForm()">
ÚJ FIÓK LÉTREHOZÁSA
</button>
<div class="link">
<span>Már van fiókod? </span>
<a href="#" (click)="backToLogin()">Jelentkezz be</a>
</div>
</form>
</kendo-card>
<lang-selector></lang-selector>
</div>
It works, but with the following side effect. F. e. if I type 'a' in the password field and then 'b' in the confirm password field, I get the error message. Fine. Now, if I change 'b' to 'a', the error message is gone, form can be submitted. Fine. But if I change the first password ('a') to 'b', the error message disappears too, but the confirm password field remains red and I can't submit the form. The form itself has no more errors (I have checked it in the console), but the field itself has still this matching
error. Why is this?
The problem is here Validation.match
controls?.get(checkControlName)?.setErrors({ matching: true });
You are manually setting validation on checkControlName
, but it should be on formGroup. Due to which somehow validation is mixing up and which is resulting in unexpected validation. I tried to figure out the scenario but did not able to find it.
To resolve your problem.
Remove controls?.get(checkControlName)?.setErrors({ matching: true });
which is inside if (control?.value !== checkControl?.value)
Add below getter in component.ts: - To get FormGroup, so that we can use it in our template for validation.
get fg(): FormGroup {
return this.signupForm as FormGroup;
}
Change
<kendo-formerror *ngIf="signupForm.errors?.matching">
A két jelszó nem egyezik
</kendo-formerror>
To
<kendo-formerror *ngIf="fg.hasError('matching')">
A két jelszó nem egyezik
</kendo-formerror>
That's it : Similar Demo