角度2:遍历反应式表单控件


Answers:


198

发现Object.keys可以解决这个问题。

    Object.keys(this.form.controls).forEach(key => {
      this.form.get(key).markAsDirty();
    });

对于Angular 8+,请使用以下内容(基于米开朗基罗的答案):

    Object.keys(this.form.controls).forEach(key => {
      this.form.controls[key].markAsDirty();
    });

2
在onSubmit中使用此功能时,出现错误Cannot invoke an expression whose type lacks a call signature. Type 'AbstractControl' has no compatible call signatures.有人知道为什么吗?
maidi

1
Object.keys(this.registerForm.controls).forEach(key => {this.registerForm.controls [key] .markAsDirty();});
Foad

当我尝试Object.keys甚至是“ for in”时,我什么也没得到。但是,如果我使用console.log(form.controls),则可以查看该对象包含的所有各种表单控件。我很困惑。
杰克·沙克斯沃思

使用Angular 5,markAsDirty()/ markAsTouched()不会递归到任何子FormGroups中。我将上面的代码分解成一个递归函数,并在任何子FormGroups上调用了它。如果用户从未触摸过必需的元素,则可使用当前的Angular Material UI项目更好地工作,当用户尝试提交该表单以标记任何元素时,我将其调用。
罗伯特

3
感谢您阅读我的帖子并更新您自己的答案。官方文档也已过时,因此我不得不通过打印每一行来弄清楚这一点……
Michelangelo

55

对于它的价值,还有另一种无需使用Object.keys(...)魔法的方法:

for (const field in this.form.controls) { // 'field' is a string

  const control = this.form.get(field); // 'control' is a FormControl  

}

如何获得循环索引?
SVK

1
对于使用TSLint的用户,该代码有效,但是TSLint抱怨“必须使用if语句(forin)过滤for(... in ...)语句”。
Yennefer

1
tslint时指出,从对... in语句的JavaScript的文档报价 stackoverflow.com/questions/40770425/...
埃格勒Kreivyte

41

接受的答案对于平面结构是正确的,但不能完全回答原始问题。网页可能需要嵌套的FormGroups和FormArrays,我们必须考虑到这一点才能创建可靠的解决方案。

public markControlsDirty(group: FormGroup | FormArray): void {
    Object.keys(group.controls).forEach((key: string) => {
        const abstractControl = group.controls[key];

        if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) {
            this.markControlsDirty(abstractControl);
        } else {
            abstractControl.markAsDirty();
        }
    });
}

instanceof在被Typescript编译后将始终有效吗?
值得注意的是

@ the-notableinstanceof并非特定于TypeScript的关键字(developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…)也不是class数据类型。
基南·迪格斯

7

使用@Marcos答案,我创建了一个函数,可以调用该函数,将formGroup作为参数传递,并将每个formGroup子控件标记为脏,例如,使其在代码周围的更多位置可用,例如将其放入服务中。

public touchAllFormFields(formGroup: FormGroup): void {
    Object.keys(formGroup.controls).forEach((key) => {
        formGroup.get(key).markAsDirty();
    });
}

希望能帮助到你 ;)


完善!已添加到服务中,并带有与clearValidators,取消接触等类似的功能。可能想为嵌套控件添加递归检查,但这目前仍然有效。谢谢!
mc01

6

似乎该get 函数不再可用于在Angular 8中检索表单中的特定值,因此这就是我根据@Liviu Ilea的答案解决的方法。

for (const field in this.myForm.controls) { // 'field' is a string
  console.log(this.myForm.controls[field].value);
}

你确定吗?API文档已经具有抽象控件的get方法(angular.io/api/forms/AbstractControl#get)。我还没有迁移。现在我很害怕(⊙_◎)
艾伦·格罗兹

@AlanGrosz是的,我在重写它时也看到了,但是即使在控制台中打印所有行时,我也找不到该对象上的任何get方法。我认为文档落后了。祝你好运!
米开朗基罗

我认为他们没有删除它,而是在Angular 8中为我工作。它仍然在documentation angular.io/api/forms/AbstractControl#get
Laszlo Sarvold

5

    Object.keys( this.registerForm.controls).forEach(key => {
       this.registerForm.controls[key].markAsDirty();
    });


3

这对我有用

private markFormGroupTouched(formGroup: FormGroup) {
  Object.keys(formGroup.controls).forEach((key) => {
    const control = formGroup.controls[key];
    control.markAsDirty();
    if ((control instanceof FormGroup)) {
      this.markFormGroupTouched(control);
    }
  });
}

1

我创建此函数是为了使它*我有一个名为“ order”的控件,并将索引传递给他。

{"conditionGroups": [
   {
     "order": null,
     "conditions": []
   }
  ]
}


updateFormData() {
    const control = <FormArray>this.form.controls['conditionGroups'];  
    control.value.map((x,index)=>{
    x.order = index; 
 })
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.