On our registration form we have a password
field and a confirmPassword
field.
We want to validate that the confirmPassword
field matches the password
field prior to enabling the submit button for the form.
If the passwords do not match then the mat-error
notification below the confirmPassword
field will display a message indicating this.
Approach
Matching the Passwords
First within our validation.service.ts
service we will create a factory function used to produce the ValidatorFn
instance that will check whether the passwords match.
passwordMatch(password: string, confirmPassword: string): ValidatorFn {
return (formGroup: AbstractControl): { [key: string]: any } | null => {
const passwordControl = formGroup.get(password);
const confirmPasswordControl = formGroup.get(confirmPassword);
if (!passwordControl || !confirmPasswordControl) {
return null;
}
if (
confirmPasswordControl.errors &&
!confirmPasswordControl.errors.passwordMismatch
) {
return null;
}
if (passwordControl.value !== confirmPasswordControl.value) {
confirmPasswordControl.setErrors({ passwordMismatch: true });
return { passwordMismatch: true };
} else {
confirmPasswordControl.setErrors(null);
return null;
}
};
}
If the there are no errors then null is returned. If the passwords do no match we set the passwordMismatch
error on the confirmPasswordControl
.
Creating the Reactive Form
Note that the passwordMatch
function is passed in as the second argument in the FormGroup
constructor:
public registrationForm: FormGroup = new FormGroup(
{
password: new FormControl('', [
Validators.required,
Validators.minLength(8),
Validators.maxLength(32),
this.v.passwordMinLowerCaseLettersValidator(),
]),
confirmPassword: new FormControl(
'',
Validators.compose([Validators.required])
),
},
this.v.passwordMatch('password', 'confirmPassword')
);
Creating the Reactive Form Template
<mat-card style="min-width: 10rem; max-width:30rem;margin: 2rem;">
<form
fxLayoutAlign="stretch"
fxLayout="column"
[formGroup]="registrationForm"
(ngSubmit)="submit()"
>
<mat-form-field>
<input
matInput
type="password"
placeholder="Password"
formControlName="password"
/>
<mat-hint *ngIf="!passwordValue">Example @123PASSWord</mat-hint>
<mat-error *ngIf="passwordControl.invalid">{{
getPasswordError()
}}</mat-error>
</mat-form-field>
<mat-form-field>
<input
matInput
type="password"
placeholder="Confirm Password"
formControlName="confirmPassword"
/>
<mat-error *ngIf="confirmPasswordControl.invalid"
>Passwords do not match
</mat-error>
</mat-form-field>
<button mat-button type="submit" [disabled]="!registrationForm.valid">
Register
</button>
</form>
</mat-card>