我正在尝试为我的 FormControl 制作自定义验证器
mealType
如果我的 FormControl
category
有值而 mealType
没有,则 mealType
应该无效。
如果
category
没有值,则 mealType
应该有效。
我收到控制台错误:
类型错误:无法读取未定义的属性“get”
代码:
ngOnInit() {
this.findForm = this.formBuilder.group({
categories: [null, Validators.required],
mealTypes: [null, this.validateMealType],
distanceNumber: null,
distanceUnit: 'kilometers',
keywords: null,
});
}
validateMealType() {
if (this.findForm.get('categories').value) {
if (this.findForm.get('mealTypes').value) {
var mealTypeError = false;
} else {
var mealTypeError = true;
}
} else {
var mealTypeError = false;
}
return mealTypeError ? null : {
error: true
}
}
这是我的形式未定义。
我该如何解决这个问题?
试试这个:
validateMealType(categoryControl: FormControl, mealTypeControl: FormControl) {
if (categoryControl.value) {
if (!mealTypeControl.value) {
var mealTypeError = true;
} else {
var mealTypeError = false;
}
} else {
var mealTypeError = false;
}
return mealTypeError ? null : {
error: true
}
}
但它会导致:
错误 应用程序/find-page/subcomponents/find-page/find-form.component.html:36:5 原因:无法读取未定义的属性“值”
尝试这个:
class MealTypeValidator {
constructor(private categoryFormControl: FormControl) { }
mealTypeValidator(control: FormControl): { [error: string]: any } {
if (this.categoryFormControl.value) {
if (!control.value) {
return { error: true };
}
}
}
}
然后在我的表单组件中:
ngOnInit() {
this.findForm = this.formBuilder.group({
categories: [null, Validators.required],
mealTypes: [null, new MealTypeValidator(this.findForm.get('categories').mealTypeValidator()],
distanceNumber: null,
distanceUnit: 'kilometers',
keywords: null,
});
}
但我有编译错误。我怎样才能做到这一点?我认为我对我所做的验证类和它的使用都有点偏离。
你又近了一步。
您需要将自定义验证器附加到
FormGroup
,因为它需要知道两个 FormControl
(categories
和 mealTypes
),因此附加到 FormGroup
将为验证器提供更广泛的视图和访问权限整个FormControl
要实现这一点,请将您的
ngOnInit
更改为
ngOnInit() {
this.findForm = new FormGroup({
mealTypes : new FormControl(null, Validators.Required),
categories : new FormControl(null)
// others form control here
}, validateMealType); // <-- see here is your custom function
}
在上面的代码中,您实际上必须使用
FormGroup
构造函数而不是 FormBuilder
,因此您可以在参数中附加自定义验证。另外,将自定义验证器移到组件类之外。
看看这个 Plunker 以获得有关您的具体案例的更多见解。
您可以通过该控件及其父表单组导航到另一个控件:
example(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const forbidden = control.value < control.parent.controls["anotherControl"].value;
return forbidden ? { forbidden: { message: "Custom message" } } : null;
};
}
将上述内容添加为组件内的函数,并向表单控件声明此验证器:
formGroup = new FormGroup({
//..
targetControl: new FormControl("", [this.example()]),
anotherControl: new FormControl("")
//..
});
注释: 进行跨字段验证的正确方法是在表单组级别使用自定义验证器。在这种情况下,生成的错误也会出现在同一级别上。现在,如果您希望为特定控件分配错误,您可以使用我上面的建议,但您需要记住,每次感兴趣的控件的值发生变化时,您都必须手动更新它们的值和有效性,如果您使用默认的“更改时更新”策略。 (因为一旦更新依赖的控件,控件的有效性可能会改变,而 Angular 只更新值发生变化的控件)
@Michael 提出的解决方案对我来说很有效,但对 Angular 4 做了一些小改动。
在验证函数中,我需要将参数类型从AbstractControl更改为FormGroup,因为该版本中的AbstractControl不包含控件集合。
function validateEqual(form: FormGroup): { [key: string]: boolean } {
const senha = form.controls['novaSenha'];
const confirmacaoSenha = form.controls['confirmacaoNovaSenha'];
if (senha != undefined && confirmacaoSenha != undefined) {
const senhaValue = senha.value;
const confirmacaoSenhaValue = confirmacaoSenha.value;
if (senhaValue !== confirmacaoSenhaValue) {
return { 'A senha e a confirmação não coincidem.': true};
}
return null;
}
}
也感谢@Ariel,他创建了这篇文章。
mealTypes: [null, new MealTypeValidator(this.findForm.get('categories').mealTypeValidator()]
但是我们可以从控制中获取父级,并使用可选运算符我们可以引用值并获取另一个控制值,然后比较我们需要的任何逻辑。
ngOnInit() {
this.findForm = this.formBuilder.group({
categories: [null, Validators.required],
mealTypes: [null, this.mealTypeValidator()],
distanceNumber: null,
distanceUnit: 'kilometers',
keywords: null,
});
}
mealTypeValidator(): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
return control.parent?.value.categories && !control.value
? { forbidden: { message: 'MealType should have a type under category!' } }
: null;
};
}