【问题标题】:How to force a field in an angular reactive form to re-run validation如何强制以角度反应形式的字段重新运行验证
【发布时间】:2020-01-30 02:40:27
【问题描述】:

我将 Angular 与反应形式和材质 UI 一起使用。我有一个表单,其中有一个文本字段,仅当另一个字段具有特定值时才需要该字段 - 例如,仅在选择单选按钮时才出现且需要的文本输入。这是一个示例代码sn-p:

<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>

我的问题是第一次绘制表单时调用了验证,并且它通过了,因为没有检查按钮。但是当用户单击单选按钮时,该字段将不会重新运行其验证,因为它没有被更改。

现在我手动将关注字段的值设置为自身,以便重新运行验证,但感觉就像是 hack。

public applyForm(formValue) {
    this.formIsSubmitted = true;
    const concernsField= this.form.get('concerns');
    concernsField.setValue(concernsField.value);
    if (this.form.valid) {
        this.submitFormValue(formValue);
    }
}

有没有更好的方法?如果我有一个大表格,这会变得笨拙。我看到有一个 setDirty 方法,但我在表单和控件上都尝试了它,但它似乎没有做任何事情。

【问题讨论】:

  • 在 changedetectorref 中听起来像是 markForCheck 的工作,但需要更多示例来了解发生了什么,例如,如果您有 onPush 检测策略并且在任何地方分离等等。

标签: angular angular-reactive-forms


【解决方案1】:

如果您有一个大表单,我会为那些相互依赖的控件创建一个嵌套表单组,然后将自定义验证器附加到该嵌套表单上。例如:

this.form = this.fb.group({
  nested: this.fb.group(
    {
      haveConcerns: [false],
      concerns: [""]
    },
    { validators: concernValidator }
  )
});

只要任何一个 formcontrol 值发生变化,就会触发它。

DEMO HERE

您当然也可以在主表单上附加验证器,但如果您有一个非常大的表单,则在编辑非相关字段时它会不必要地触发。

如果你这样做,你需要创建一个自定义错误状态匹配器,因为mat-error 不会在表单组有错误时显示,只有当表单控件有错误时才会显示。如何为此目的制作自定义错误状态匹配器,可以找到 here


如果您真的只想在concerns 表单控件上使用验证器,正如您所注意到的,您必须以某种方式在haveConcerns 更改时触发该表单控件上的验证。您可以通过监听该表单控件的valueChanges(或只是一个监听更改的函数)并调用this.form.get('concerns).updateValueAndValidity() 来实现这一点,这将触发该字段的自定义验证器,例如:

this.form.get("haveConcerns").valueChanges.subscribe(data => {
  this.form.get('concerns').updateValueAndValidity();
});

如果您这样做,请记住取消订阅组件OnDestroy

【讨论】:

    猜你喜欢
    • 2018-12-28
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 2018-02-19
    相关资源
    最近更新 更多