提问人:Wouter Vandenputte 提问时间:10/27/2023 更新时间:10/29/2023 访问量:67
Angular Reactive form:指定 WHEN 验证
Angular Reactive form: specify WHEN to validate
问:
条件验证器可能被问了很多。但是我永远找不到何时调用这个验证器。
假设我有一个只有两个字段的表单
this.form = formBuilder.group({
emailRequired: [false],
emailRecipients: ['']
});
我现在希望该字段仅在字段设置为 时才具有必需的验证器。我想出了这个emailRecipients
emailRequired
true
const emailRecipientsControl = fb.control('', {
validators: [
(x) =>
{
// When emailRequired is set to true, the email control is required.
if (x.parent?.get('emailRequired').value)
{
return { required: true }
};
return null;
}
]
});
this.form = this.fb.group({
emailRequired: [false],
emailRecipients: emailRecipientsControl
});
这实际上在某种程度上是有效的,但问题是我的自定义验证器仅在值已更改时调用,而我需要在两者或已更改时调用它。emailRecipients
emailRecipients
emailRequired
总而言之:如何定义何时调用(自定义)控件验证?
注意:我的真实表单比这个例子大得多,我宁愿不订阅整个表单。
答:
2赞
MoxxiManagarm
10/27/2023
#1
您需要订阅 valuechanges 并添加/删除验证器。
this.form = formBuilder.group({
emailRequired: [false],
emailRecipients: ['']
});
this.form.controls.emailRequired.valueChanges.pipe(
/*unsubscription*/,
).subscribe(isRequired => {
if (isRequired) {
this.form.controls.emailRecipients.addValidators(Validators.required);
} else {
this.form.controls.emailRecipients.removeValidators(Validators.required);
}
this.form.controls.emailRecipients.updateValueAndValidity();
});
评论
0赞
Eliseo
10/27/2023
请不要删除/添加验证者。有更好的解决方案。在这种情况下,很简单,在复选框的输入中调用“this.form.controls.emailRecipients.updateValueAndValidity()”
0赞
Eliseo
10/29/2023
根据您的建议,我想象了一个“新”解决方案。验证器“checkControl”。我更新我的答案,希望你喜欢:)
0赞
Eliseo
10/27/2023
#2
正如您所说,如果您不使用 setValue 或更改输入,Angular 不会“自动验证”输入。因此,更简单的解决方案是在更改复选框时强制执行此验证
<input type="check" formControlName="emailRequired"
(input)="form.controls.emailRecipients.updateValueAndValidity()">
更新基于@MoxxiManagarm的推荐。如果我们可以定义我们的 formGroup,并且不需要在需要订阅 valueChanges 或使用(输入)时考虑,那就更好了。
我们可以定义一个“验证器”,如
export function checkControl(controlName:string)
{
return (x:AbstractControl) =>
{
const control=x?.parent?.get(controlName);
if (control)
control.updateValueAndValidity()
return null;
}
}
这允许我们写
form = new FormGroup({
emailRequired: new FormControl(false,checkControl('emailRecipients')),
emailRecipients: new FormControl('',requireIf('emailRequired'))
});
然后我们简单
<form [formGroup]="form">
<input type="checkbox" formControlName="emailRequired">
<input formControlName="emailRecipients">
{{form.get('emailRecipients')?.errors|json}}
</form>
注意:验证器“requiredIf”喜欢
export function requireIf(controlName:string)
{
return (x:AbstractControl) =>
{
if (x?.parent?.get(controlName)?.value && !x.value)
{
return { required: true }
};
return null;
}
}
看到,当我们更改“复选框”时,formControl 是 updateAndValidity。form.controls.emailRecipiens
好吧,这个“验证器”使典型的重复密码验证器问题更加“健壮”。
export function equalsTo(controlName:string)
{
return (x:AbstractControl) =>
{
const control=x?.parent?.get(controlName);
if (control && control.value && control.value!=x.value)
{
return { notMatch: true }
};
return null;
}
}
表格
form2=new FormGroup({
password:new FormControl('',checkControl('repeatPassword')),
repeatPassword:new FormControl('',equalsTo('password'))
})
评论
0赞
MoxxiManagarm
10/27/2023
我在这里看到的最大问题来自维护的角度。想象一下,在某个时候,emailRequired 不仅会由用户输入设置,而且还会以编程方式设置。您将始终需要记住,在更改 emailRequired 的每个点上,您还需要更新有效性。这是一个巨大的错误风险。通过列出值本身,您可以一次处理所有这些情况,并且不需要一些自定义验证器。
0赞
Eliseo
10/28/2023
@MoxxiManagarm,但是,为什么在更改时也不只updateValueAndValidity?真的,我不喜欢删除/添加验证器。注意:这只是一个非常非常个人的意见。
评论