After creating a form using Reactive Forms, I have implemented functionality for users to set a new password. The process involves entering both the old and new passwords, as well as confirming the new password. Throughout development, I considered the following scenarios:
- The new password cannot be the same as the old password
- The new password and confirmation password must match
While the development is functional, there is one aspect that could be improved. Currently, validation only occurs when something in an input field is changed. However, I would like the validation to occur when changing the new password to confirm it instantaneously for any errors. I've come across the updateValueAndValidity function that can potentially help with this. Can anyone provide guidance on how to implement this?
Here's a snippet of my code:
// TS
changePasswordForm: FormGroup;
submitted = false;
ngOnInit() {
// Initialize forms
this.initChangePasswordForm();
}
private initChangePasswordForm() {
// Form initialization
this.changePasswordForm = this.formBuilder.group({
old_password: [null, Validators.pattern('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^\\w\\s]).{8,}$')],
new_password: [null, this.customComparePasswordValidator],
confirm_password: [null, Validators.required]
});
}
customComparePasswordValidator(control: FormControl) {
const newPassword = control.value;
if (newPassword && newPassword.length) {
const oldPassword = control.parent.value.old_password;
if (oldPassword && oldPassword.length && newPassword.toLowerCase().includes(oldPassword.toLowerCase())) {
return { newPasswordIncludesOldPassword: true };
}
const pattern = new RegExp('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^\\w\\s]).{8,}$');
if (!pattern.test(newPassword)) {
return { newPasswordInvalid: true };
}
} else {
return { required: true };
}
}
// HTML
<input matInput type="password" placeholder="Current Password" formControlName="old_password" required>
<p *ngIf="changePasswordForm.get('old_password').invalid && (changePasswordForm.get('old_password').dirty || changePasswordForm.get('old_password').touched)">
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('old_password').hasError('required')">Please enter current password</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('old_password').hasError('pattern')">Use 8 or more characters with a mix of uppercase and lowercase letters, numbers, and symbols</mat-error>
</p>
<input matInput type="password" placeholder="New Password" formControlName="new_password" required>
<p *ngIf="changePasswordForm.get('new_password').invalid && (changePasswordForm.get('new_password').dirty || changePasswordForm.get('new_password').touched)">
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('new_password').hasError('required')">Please enter new password</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('new_password').hasError('newPasswordInvalid')">Use 8 or more characters with a mix of uppercase and lowercase letters, numbers, and symbols</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('new_password').hasError('newPasswordIncludesOldPassword')">New password should not include old password</mat-error>
</p>
<input matInput type="password" placeholder="Confirm Password" formControlName="confirm_password" appConfirmEqualValidator="new_password" required>
<p *ngIf="changePasswordForm.get('confirm_password').invalid && (changePasswordForm.get('confirm_password').dirty || changePasswordForm.get('confirm_password').touched)">
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('confirm_password').hasError('required')">Please confirm the password</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('confirm_password').hasError('notEqual') && !changePasswordForm.get('confirm_password').hasError('required')">Passwords do not match</mat-error>
</p>
You can access my StackBlitz project at: https://stackblitz.com/edit/example-angular-material-reactive-form-sr1keu?file=app%2Fapp.component.html