【问题标题】:Angular form updateValueAndValidity of all children controls所有子控件的角度形式 updateValueAndValidity
【发布时间】:2018-04-09 23:38:30
【问题描述】:

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

在某些时候我需要强制更新它们的有效性,所以我正在这样做:

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

然后:

this.form.updateValueAndValidity();

这很好用。

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

根据其documentationupdateValueAndValidity()方法:

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

但就我而言,我需要更新其后代的价值和有效性。这样我就可以去掉很多行代码了。

【问题讨论】:

  • 您是否尝试过查看它是否确实更新其后代?
  • 类似...?
  • ...不先直接调用后代的方法?我原以为updateValueAndValidity 也适用于子表单。
  • 当然可以,但它不起作用
  • 有趣的问题。我认为它不是开箱即用的,在这种情况下markAsDirty 存在同样的问题:github.com/angular/angular/issues/11774 我认为您需要做一些解决方法并迭代父对象中的对象属性并在每个控件上使用updateValueAndValidity。唔。如果只在父级上调用它就可以了。

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


【解决方案1】:

如果您需要触发对控件及其后代的验证,有一种解决方法可以调用updateTreeValidity,而它不是公共 API 的一部分:

(<any>form)._updateTreeValidity({ emitEvent: false });

问题正在这里跟踪:https://github.com/angular/angular/issues/6170

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,其中一个问题是收听valueChanges observable 并触发updateValueAndValidity 来运行我的验证器导致了一个无限循环,所以为了解决(而且有点hacky?)我创建了组件变量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】:

      我在嵌套级别控件中更新 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();
          }
        });
      }
      

      【讨论】:

        【解决方案4】:
        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);
            }
          }
        

        【讨论】:

        • 将控件标记为已触摸是其他答案中缺少的内容!
        【解决方案5】:

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

        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 });
        }
        

        【讨论】:

          【解决方案6】:

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

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

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

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

          【讨论】:

            猜你喜欢
            • 2021-08-30
            • 1970-01-01
            • 1970-01-01
            • 2020-09-28
            • 2021-09-25
            • 2016-03-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多