In this tutorial the author implements a password check validator like this:
MatchPassword(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);
}
}
}
No return type is set for the function. This leads to linting errors in Angular 13.
I've tried to fix the linting errors by changing the signature of the cross property validation function to this:
MatchPassword(password: string, confirmPassword: string):ValidatorFn | ValidatorFn[] | AbstractControlOptions | null | undefined { ...
However now the linter errors on the signature of the validation function that is returned:
...
return (formGroup: FormGroup):ValidatorFn | ValidatorFn[] | AbstractControlOptions | null | undefined => {
...
Type '(formGroup: FormGroup) => ValidatorFn | ValidatorFn[] | AbstractControlOptions | null | undefined' is not assignable to type 'ValidatorFn | AbstractControlOptions | ValidatorFn[] | null | undefined'.
Type '(formGroup: FormGroup) => ValidatorFn | ValidatorFn[] | AbstractControlOptions | null | undefined' is not assignable to type 'ValidatorFn'.
Types of parameters 'formGroup' and 'control' are incompatible.
Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more.ts(2322)
This does not happen on Stackblitz, only on new Angular 13 projects, thus I can't create a Stackblitz for it.
Anyone know how to declare the signature for Reactive Form Validators that perform cross property validation?
For those wondering, the very first linting error occurs within the registration component that is assigning the cross property validator.
It creates the FormGroup
instance and the custom cross property validator is assigned as the third argument like this:
new FormGroup('', ..., this.v. MatchPassword('password', 'confirmPassword'))
And that is where the first linting error occurs.
** Side Note **
this.v
is the injected validation service containing the MatchPassword
function.
The linting error generated says this:
Argument of type '(formGroup: FormGroup) => null | undefined' is not assignable to parameter of type 'ValidatorFn | ValidatorFn[] | AbstractControlOptions | null | undefined'.
Type '(formGroup: FormGroup) => null | undefined' is not assignable to type 'ValidatorFn'.
Types of parameters 'formGroup' and 'control' are incompatible.
Type 'AbstractControl' is missing the following properties from type 'FormGroup': controls, registerControl, addControl, removeControl, and 3 more.ts(2345)
if you'd like to do cross field validation that is easy because when passed into the new FormGroup(...)
the validator gets the actual FormGroup
. but for typing Angular has (control: AbstractControl)
and that is fine because
FormGroup
is actually a type of AbstractControl
. so all you need to do is to check that this is a FormGroup
and not one of the other types of AbstractControl
s so you could do
MatchPassword(password: string, confirmPassword: string) {
return (control: AbstractControl) => {
const isFormGroup = control instanceof FormGroup;
if (!isFormGroup) {
return null
}
// do what ever you'd like...
const passwordControl = formGroup.controls[password];
const confirmPasswordControl = formGroup.controls[confirmPassword];