I'm trying to create a material password confirmation component that can be used with Angular Reactive Forms. This way the same component can be used in a Registration Form and a Reset Password Form.
I've created a self contained Stackblitz Demo here that works fine (This is when the control is used standalone without being embedded in another reactive form). The password field has min and max length validation constraints on it and the confirm password field is required.
The submit button will not enable until all the validation constraints are satisfied and the passwords match.
So now I'd like to be able to use the component in Angular Material Reactive Forms, and according to this article the control must implement the ControlValueAccessor interface and the Validator interface.
So I've added these to the control and I've implemented a demo here.
The form looks like this:
<mat-card class="PasswordFormTestCard">
<form class="RegistrationForm" [formGroup]="form" (ngSubmit)="submit()">
<mat-form-field>
<input
matInput
placeholder="username"
type="text"
formControlName="username"
/>
<mat-hint *ngIf="!username">Example Monica</mat-hint>
<mat-error>Please enter your username</mat-error>
</mat-form-field>
<fs-password-form formControlName="password"></fs-password-form>
<button mat-button type="submit" [disabled]="!form.valid">Submit</button>
</form>
</mat-card>
As can be seen the custom password form control is bound like this:
<fs-password-form formControlName="password"></fs-password-form>
And this "Almost" works.
The submit button enables as soon as the confirmPassword dialogs has any characters in it.
The validate function on the control should prevent this from happening. I've implemented it like this:
//=============================================
// Validator API Methods
//=============================================
validate(control: AbstractControl): ValidationErrors | null {
if (
this.passwordForm.valid &&
this.confirmPasswordControl.valid &&
this.passwordControl.valid
) {
console.log('BOTH THE FORM AND THE CONTROLS ARE VALID');
return null;
}
let errors: any = {};
errors = this.addControlErrors(errors, 'password');
errors = this.addControlErrors(errors, 'confirmPassword');
return errors;
}
addControlErrors(allErrors: any, controlName: string) {
const errors = { ...allErrors };
const controlErrors = this.passwordForm.controls[controlName].errors;
if (controlErrors) {
errors[controlName] = controlErrors;
}
return errors;
}
And I thought checking that the the form and the controls are valid before returning null like this:
this.passwordForm.valid &&
this.confirmPasswordControl.valid &&
this.passwordControl.valid
Would ensure that the custom PasswordForm control does not indicate that it is valid before it actually is, but it's returning null early for some reason.
Anyone have any ideas on why this is?