I’m following this tutorial for how to validate confirm passwords with Angular Reactive Forms.
I created a Stackblitz for the implementation.
The implementation for the confirm password function comes from the tutorial and looks like this:
passwordMatch(password: string, confirmPassword: string) { return (formGroup: FormGroup) => { const passwordControl = formGroup.controls[password]; const confirmPasswordControl = formGroup.controls[confirmPassword]; if (!passwordControl || !confirmPasswordControl) { return null; } if ( confirmPasswordControl.errors && !confirmPasswordControl.errors.passwordMismatch ) { return null; } if (passwordControl.value !== confirmPasswordControl.value) { confirmPasswordControl.setErrors({ passwordMismatch: true }); } else { confirmPasswordControl.setErrors(null); } }; }
If I try to add it to a composed validator like this:
confirmPassword: new FormControl( '', Validators.compose([ Validators.required, this.v.passwordMatch('password', 'confirmPassword'), ]) ),
Angular creates an error that says:
ERROR Error: Cannot read properties of undefined (reading 'password')
How do we add a validator that performs cross property validation?
Right now this Stackblitz Demo works:
https://stackblitz.com/edit/angular-ivy-f5dj86?file=src%2Fapp%2Fregistration.component.ts
Because the cross password validation is commented out:
confirmPassword: new FormControl( '', Validators.compose([ Validators.required, // this.v.passwordMatch('password', 'confirmPassword'), ]) ),
Advertisement
Answer
Since the validator needs access to both password control values to compare them, you have to use it as a FormGroup validator. So you just have to move the validator to the second argument of the FormGroup
constructor like this
public registrationForm: FormGroup = new FormGroup({ email: new FormControl(...), password: new FormControl(...), confirmPassword: new FormControl(...), }, this.v.passwordMatch('password', 'confirmPassword') );
cheers