I have developed a form in Reactive Forms where the user has the possibility to set a new password. He enters the old and the new password and confirms the new password. I have considered the following cases:
- New password must not contain the old password
- New password and confirmation password are matched
The development works as well. Now I have one thing that is not nice. The validation is triggered only when I change something in the input field. But now I want to change the new password when I want to confirm the password, so I know if there is an error or not. I have read that this can be done with the function updateValueAndValidity. Do you know how to do this?
My Code:
// TS
changePasswordForm: FormGroup;
submitted = false;
ngOnInit() {
// To initialize forms
this.initChangePasswordForm();
}
// Creation of the changePasswordForm
private initChangePasswordForm() {
// General
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="aktuelles Passwort" 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')">aktuelles Passwort eingeben</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('old_password').hasError('pattern')">8 oder mehr Zeichen mit einer Mischung aus Groß- und Kleinbuchstaben, Ziffern und Symbolen verwenden</mat-error>
</p>
<input matInput type="password" placeholder="neues Passwort" 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')">neues Passwort eingeben</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('new_password').hasError('newPasswordInvalid')">8 oder mehr Zeichen mit einer Mischung aus Groß- und Kleinbuchstaben, Ziffern und Symbolen verwenden</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('new_password').hasError('newPasswordIncludesOldPassword')">Neues und altes Passwort dürfen nicht gleich sein</mat-error>
</p>
<input matInput type="password" placeholder="Passwort bestätigen" 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')">Passwort erneut eingeben</mat-error>
<mat-error class="custom-validation-error" *ngIf="changePasswordForm.get('confirm_password').hasError('notEqual') && !changePasswordForm.get('confirm_password').hasError('required')">Passwort stimmt nicht überein</mat-error>
</p>
My StackBlitz: https://stackblitz.com/edit/example-angular-material-reactive-form-sr1keu?file=app%2Fapp.component.html