我正在将Angular用于反应形式和材料UI。我有一个表单,其中有一个文本字段,仅当另一个字段具有某个值时才需要该文本字段-例如,仅选择一个单选按钮时,文本输入才出现并且是必需的。这是一个示例代码片段:
<div>
Do you have any concerns?
</div>
<mat-radio-group formControlName="haveConcerns">
<mat-radio-button [value]=true>yes</mat-radio-button>
<mat-radio-button [value]=false>no</mat-radio-button>
</mat-radio-group>
<div [hidden]="!form.value.haveConcerns">
<div>
if "YES", please list the reasons:`enter code here`
</div>
<mat-form-field>
<input formControlName="concerns" matInput placeholder="reasons" type="text">
<mat-error *ngIf="hasError(this.form, 'concerns', 'maybeRequired')">
please explain any concerns your may have
</mat-error>
</mat-form-field>
</div>
我的问题是,第一次绘制表单时会调用验证,并且该验证通过了,因为未选中该按钮。但是,当用户单击单选按钮时,由于该字段未更改,因此不会重新运行其验证。
现在,我正在手动将担忧字段的值设置为其自身,以使验证重新运行,但是感觉就像是黑客。
public applyForm(formValue) {
this.formIsSubmitted = true;
const concernsField= this.form.get('concerns');
concernsField.setValue(concernsField.value);
if (this.form.valid) {
this.submitFormValue(formValue);
}
}
有更好的方法吗?如果我有一个大表格,这将变得很笨拙。我看到有一个setDirty方法,但是我在窗体和控件上都尝试了它,但它似乎没有做任何事情。
答案 0 :(得分:2)
如果您的表单很大,我将为彼此依赖的控件创建一个嵌套的表单组,然后在该嵌套的表单上附加自定义验证器。例如:
this.form = this.fb.group({
nested: this.fb.group(
{
haveConcerns: [false],
concerns: [""]
},
{ validators: concernValidator }
)
});
,然后在任何一个formcontrol值更改时将触发它。
您当然也可以在主表单上附加验证器,但是如果表单很大,则在编辑无关字段时会不必要地触发。
如果执行此操作,则需要创建自定义错误状态匹配器,因为如果表单组有错误,则仅在formcontrol发生错误时才显示mat-error
。 here 。可以找到如何为此目的创建自定义错误状态匹配器。
如您所注意到的,如果您真的只想在concerns
表单控件上使用验证器,则无论何时haveConcerns
发生变化,都必须以某种方式触发对该表单控件的验证。您可以通过侦听该表单控件的valueChanges
(或仅侦听更改的函数)并调用this.form.get('concerns).updateValueAndValidity()
来实现此目的,这将触发该字段的自定义验证器,例如:
this.form.get("haveConcerns").valueChanges.subscribe(data => {
this.form.get('concerns').updateValueAndValidity();
});
如果这样做,请记住退订组件OnDestroy