Confirm password validation in Angular 6
You can simply use password field value as a pattern for confirm password field.
For Example:
<div class="form-group">
<input type="password" [(ngModel)]="userdata.password" name="password" placeholder="Password" class="form-control"
required #password="ngModel" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" />
<div *ngIf="password.invalid && (myform.submitted || password.touched)" class="alert alert-danger">
<div *ngIf="password.errors.required"> Password is required. </div>
<div *ngIf="password.errors.pattern"> Must contain at least one number and one uppercase and lowercase letter,
and at least 8 or more characters.</div>
</div>
</div>
<div class="form-group">
<input type="password" [(ngModel)]="userdata.confirmpassword" name="confirmpassword" placeholder="Confirm Password"
class="form-control" required #confirmpassword="ngModel" pattern="{{ password.value }}" />
<div *ngIf=" confirmpassword.invalid && (myform.submitted || confirmpassword.touched)" class="alert alert-danger">
<div *ngIf="confirmpassword.errors.required"> Confirm password is required. </div>
<div *ngIf="confirmpassword.errors.pattern"> Password & Confirm Password does not match.</div>
</div>
</div>
This question could be solved with a combination of these two answers: https://stackoverflow.com/a/43493648/6294072 and https://stackoverflow.com/a/47670892/6294072
So first of all, you would need a custom validator for checking the passwords, that could look like this:
checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => {
let pass = group.get('password').value;
let confirmPass = group.get('confirmPassword').value
return pass === confirmPass ? null : { notSame: true }
}
and you would create a formgroup for your fields, instead of just two form controls, then mark that custom validator for your form group:
this.myForm = this.fb.group({
password: ['', [Validators.required]],
confirmPassword: ['']
}, { validators: this.checkPasswords })
and then as mentioned in other answer, the mat-error
only shows if a FormControl is invalid, so you 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;
}
}
in the above you can tweak when to show error message. I would only show message when the password
field is touched. Also I would like above, remove the required
validator from the confirmPassword
field, since the form is not valid anyway if passwords do not match.
Then in component, create a new ErrorStateMatcher
:
matcher = new MyErrorStateMatcher();
Finally, the template would look like this:
<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>
Here's a demo for you with the above code: StackBlitz