在本教程中,作者实现了一个密码检查验证器,如下所示:
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);
}
}
}
函数没有设置返回类型。这会导致 Angular 13 中出现 linting 错误。
我尝试通过将交叉属性验证函数的签名更改为以下方式来修复 linting 错误:
MatchPassword(password: string, confirmPassword: string):ValidatorFn | ValidatorFn[] | AbstractControlOptions | null | undefined { ...
但是现在返回的验证函数签名上出现 linter 错误:
...
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)
这不会发生在 Stackblitz 上,只会发生在新的 Angular 13 项目上,因此我无法为其创建 Stackblitz。
有人知道如何声明执行跨属性验证的反应式表单验证器的签名吗?
对于那些想知道的人来说,第一个 linting 错误发生在分配交叉属性验证器的注册组件中。
它创建
FormGroup
实例,并将自定义交叉属性验证器指定为第三个参数,如下所示:
new FormGroup('', ..., this.v. MatchPassword('password', 'confirmPassword'))
这就是第一个 linting 错误发生的地方。
** 旁注 **
this.v
是包含 MatchPassword
函数的注入验证服务。
生成的 linting 错误说明如下:
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)
如果您想进行跨字段验证,这很容易,因为当传递到
new FormGroup(...)
时,验证器会获取实际的 FormGroup
。但对于打字 Angular 有 (control: AbstractControl)
这很好,因为
FormGroup
实际上是AbstractControl
的一种。所以您需要做的就是检查这是一个 FormGroup
而不是其他类型的 AbstractControl
之一,这样您就可以做
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];
好的,根据 Angular 团队的意见,我们将验证器的接口更改为预期的接口,并相应地更改了实现。
关键是我们可以使用
AbstractControl.get
来获取表单上的所有控件,这样我们就可以使用 ValidatorFn
界面了。
这是新的实现:
passwordMatch(password: string, confirmPassword: string):ValidatorFn {
return (formGroup: AbstractControl):{ [key: string]: any } | null => {
const passwordControl = formGroup.get(password);
const confirmPasswordControl = formGroup.get(confirmPassword);
if (!passwordControl || !confirmPasswordControl) {
return null;
}
if (
confirmPasswordControl.errors &&
!confirmPasswordControl.errors.passwordMismatch
) {
return null;
}
if (passwordControl.value !== confirmPasswordControl.value) {
confirmPasswordControl.setErrors({ passwordMismatch: true });
return { passwordMismatch: true }
} else {
confirmPasswordControl.setErrors(null);
return null;
}
};
}