[英]Custom Validator in Angular Reactive Forms not working
我在字段postalCode
上有一个自定义验证器:
function postalCodeValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!this.contactForm) {
return null;
}
const isPotalCodeRequired = this.contactForm.get(
'isPotalCodeRequired'
).value;
if (isPotalCodeRequired && !control.value) {
console.log('here');
this.contactForm.controls['postalCode'].setErrors({ required: true });
} else {
this.contactForm.controls['postalCode'].setErrors({ required: false });
}
return null;
};
}
它检查另一个字段isPotalCodeRequired
以查看是否应将验证应用于postalCode
字段。
如果isPotalCodeRequired
为真,则postalCode
需要一个值,否则它可以留空。 但是当我在postalCode
字段上调用setErrors
时,我的自定义验证似乎没有按预期工作。 它在自定义验证器函数中添加它,但在函数执行后检查它, postalCode
字段上不再存在错误。
演示。
Angular 的验证器函数有点奇怪。 当控件没有错误时,您需要返回null
并且包含错误的对象以及错误时的简要说明:
function postalCodeValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (!this.contactForm) {
return null;
}
const isPotalCodeRequired = this.contactForm.get(
'isPotalCodeRequired'
).value;
if (isPotalCodeRequired && !control.value) {
console.log('here');
return {required: 'Postal code is required' };
}
return null;
};
}
您无需手动设置错误,因为框架会为您完成
您正在尝试做的事情称为跨字段验证,通常使用跨字段验证器,您应该将验证器应用到FormGroup
而不是FormControl
。 这里,
this.contactForm = this.formBuilder.group({
isPotalCodeRequired: [true],
postalCode: [null, Validators.compose([postalCodeValidator.call(this)])],
});
您正在将您的 postalCodeValidator 绑定到特定控件。 当您应用这样的验证器时,该验证器应返回您希望应用于控件但您返回 null 的验证消息,
if (isPotalCodeRequired && !control.value) {
console.log('here');
this.contactForm.controls['postalCode'].setErrors({ required: true });
} else {
this.contactForm.controls['postalCode'].setErrors({ required: false });
}
return null;
这将清除应用于该控件的所有验证消息。 相反,将此验证器绑定到包含两个控件的FormGroup
,
this.contactForm = this.formBuilder.group({
isPotalCodeRequired: [true],
postalCode: [null]
}, {validators: Validators.compose([postalCodeValidator.call(this)])});
现在,传递给验证器的 AbstractControl 就是您的整个 FormGroup。 这样做的好处是可以访问您需要的所有控件。 因此,您将拥有的不是对this.contactForm
的引用,
control.controls['postalCode'].setErrors({ required: true });
您应该能够从验证器内部删除对this.contactForm
的所有引用。 更重要的是,您的 null 返回将不再清除单个控件上的验证消息。 查看有关响应式表单的跨字段验证的Angular 文档。
但是有一种更清洁的方法可以完全做到这一点。 无需编写自定义验证器,您只需侦听 isPostalCodeRequired 上的更改并根据需要添加/删除内置的所需验证器,
this.contactForm.get('isPostalCodeRequired').valueChanges.subscribe(val => {
if (val) {
//Add validator
else {
//Remove validator
})
可用于添加/删除验证器的辅助函数取决于您的 Angular 版本,但它们非常简单。
编辑:更新了答案以解决演示中的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.