所有子控件的角度形式updateValueAndValidity

时间:2017-10-28 14:20:16

标签: angular typescript angular-reactive-forms angular-forms angular-validation

在我的Angular 4应用程序中,我有一个包含多个控件的表单。

在某些方面,我需要强制更新其有效性,所以我正在做:

this.form.get('control1').updateValueAndValidity();
this.form.get('control2').updateValueAndValidity();
this.form.get('control3').updateValueAndValidity();
// and so on....

然后:

this.form.updateValueAndValidity();

这很好。

但是我想知道是否有更好的方法来完成相同的事情,只需在父窗体上调用一个方法。

根据其documentationupdateValueAndValidity()方法:

  

默认情况下,它还会更新祖先的值和有效性。

但在我的情况下,我需要更新其后代的价值和有效性。所以我可以摆脱许多代码。

5 个答案:

答案 0 :(得分:14)

我在相同的情况下需要在嵌套级别的控件上更新FormGroup | FormArray

检查一下(为我工作):

/**
 * Re-calculates the value and validation status of the entire controls tree.
 */
function updateTreeValidity(group: FormGroup | FormArray): void {
  Object.keys(group.controls).forEach((key: string) => {
    const abstractControl = group.controls[key];

    if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) {
      updateTreeValidity(abstractControl);
    } else {
      abstractControl.updateValueAndValidity();
    }
  });
}

答案 1 :(得分:7)

目前无法使用AbstractControl本身更新AbstractControl(FormGroup,...)的后代。也许在将来的版本中它是可能的。

https://github.com/angular/angular/issues/6170

https://github.com/angular/angular/issues/22166

更新:拉取请求已经打开 https://github.com/angular/angular/pull/19829

答案 2 :(得分:1)

我遇到了同样的问题,其中一个问题是,听valueChanges可观察并触发updateValueAndValidity来运行我的验证程序会导致无休止的循环,因此可以解决(有点怪异吗?)我创建了组件变量validityCycleFired并将其初始化为false,进行了切换并防止了失控循环:

const fireValidityCheck = () => {
     if (this.validityCycleFired) return;
     this.validityCycleFired = true;
     this.passwordForm.get('old_password').updateValueAndValidity();
     this.passwordForm.get('new_password').updateValueAndValidity();
     this.passwordForm.get('confirm_new_password').updateValueAndValidity();
     setTimeout(() => this.validityCycleFired = false, 15);
     return;
};
this.passwordForm.valueChanges.subscribe(fireValidityCheck);

答案 3 :(得分:0)

我通过递归控件并手动触发更新来解决了与您类似的问题。 可能这不是最佳解决方案:

private triggerValidation(control: AbstractControl) {
    if (control instanceof FormGroup) {
        const group = (control as FormGroup);

        for (const field in group.controls) {
            const c = group.controls[field];

            this.triggerValidation(c);
        }
    }
    else if (control instanceof FormArray) {
        const group = (control as FormArray);

        for (const field in group.controls) {
            const c = group.controls[field];

            this.triggerValidation(c);
        }
    }

    control.updateValueAndValidity({ onlySelf: false });
}

答案 4 :(得分:0)

validateFormFields(fields) {
    try {
      Object.entries(fields.controls).forEach((control: any) => {
        if (typeof control[0] == 'Array' 
        ) {
          this.validateFormFields(control[1]);
        } else {
          if (control[1].controls) {
            Object.entries(control[1].controls).forEach((c: any) => {
              c[1].touched = true;
            });
          } else {
            control[1].touched = true;
          }

        }
      });
    } catch (e) {
      console.log(e);
    }
  }