To begin, you’ll need a custom validator to validate the passwords, which may look something like this:
checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => { let password = group.get('password').value; let confirmPassword = group.get('confirmPassword').value return password === confirmPassword ? null : { notSame: true } }
Instead of simply two form controls, you’d establish a form group for your fields, and then add the custom validator to your form group:
this.myForm = this.fb.group({ password: ['', [Validators.required]], confirmPassword: [''] }, { validators: this.checkPasswords })
The mat-error only appears if a FormControl is incorrect, as explained in another response, thus you’ll need an error state matcher:
export class MyErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { const invalidCtrl = !!(control?.invalid && control?.parent?.dirty); const invalidParent = !!(control?.parent?.invalid && control?.parent?.dirty); return invalidCtrl || invalidParent; } }
You may change when the error notice appears in the aforementioned settings. Only when the password box is tapped will I display a message. Also, I’d want to remove the necessary validator from the confirm password field, because the form isn’t legitimate if the passwords don’t match in the first place.
Create a new ErrorStateMatcher in the component:
matcher = new MyErrorStateMatcher();
Finally, the template would seem as follows:
<form [formGroup]="myForm"> <mat-form-field> <input matInput placeholder="New password" formControlName="password" required> <mat-error *ngIf="myForm.hasError('required', 'password')"> Please enter your new password </mat-error> </mat-form-field> <mat-form-field> <input matInput placeholder="Confirm password" formControlName="confirmPassword" [errorStateMatcher]="matcher"> <mat-error *ngIf="myForm.hasError('notSame')"> Passwords do not match </mat-error> </mat-form-field> </form>