【问题标题】:Angular dynamic formArray can't find the controls角度动态formArray找不到控件
【发布时间】:2020-06-25 13:15:14
【问题描述】:

我在 FormArray 的帮助下构建动态表单时遇到了麻烦,我正在尝试基于包含描述数据库行的对象的数组构建表单。目标是向用户显示他选择的每一行及其当前值,让用户修改它们并将它们发回。

所以一切都需要模块化,因为我不知道他选择的行数也不知道表的列数,而且我仍然需要能够检索新数据。

我设法做了一些应该有效的事情,但我仍然有一个错误:

Error : Cannot find control with name: 'XXXXX'

我觉得这可能是关于 lifeCycleHook 的故事,并且在 typescript 中设置控件之前,html 正在以某种方式执行。

我首先创建了一个名为 modifyForm 的 formArray 和一个 formBuilder

 modifyForm: FormArray;

 constructor private fb: FormBuilder){}

然后在我的 ngOnInit 函数中,我创建了一个循环,用正确的控件填充 modifyForm 并填充 HTML 将用于创建用户界面的 externalArray。

打字稿:

ngOnInit() {


    let internalObjects = {}

    for (let i = 0; i < this.selectedRows.length; i++) {
      const row = this.selectedRows[i];
      internalObjects = {}

      for (let y = 0; y < Object.keys(row).length; y++) {
        const key = Object.keys(row)[y];
        const value = Object.values(row)[y];

        if (key !== "#") {
          this.modifyForm.push(this.fb.control(i + key))
          internalObjects[key] = value;
        }
      }
      this.externalArray.push(internalObjects)
    }
  }
}

HTML:

<form [formGroup]="modifyForm">
        <div *ngFor="let object of externalArray; let item = index ">
                <div *ngFor="let value of object | keyvalue">
                    <mat-form-field>
                       <input matInput [formControlName]='item+value.key' [value]='value.value'>
                    </mat-form-field>
               </div>
         </div>
</form>

奇怪的是,在 ngOnInit 函数结束时,我在控制台记录了它似乎使用正确值创建的控件,但它仍然说找不到它们。

打字稿循环:

   for (const control of this.modifyForm.controls) {
      console.log(control.value)
    }

结果:

我知道要消化的内容很多,我试图提供尽可能多的信息,我希望它不会太难阅读。我一直在寻找几天,我仍然被困在这里。感谢任何可以提供帮助的人! :)

【问题讨论】:

    标签: angular forms angular8 formarray dynamic-forms


    【解决方案1】:

    您没有正确绑定到表单数组。使用表单组和表单数组,您可以绑定到键。在表单数组的情况下,这是索引。

    this.modifyForm.push(this.fb.control(i + key))
    

    这是在表单数组的下一个可用索引处添加一个值为 i + key 的表单控件。

    在您的 HTML 中,您应该绑定到索引而不是值。您不需要手动设置来自表单绑定的[value]

    <input matInput [formControlName]='item' />
    

    其中item*ngFor 中定义的表单数组中的当前索引

    绑定到复杂对象

    如果您想创建一个包含多个表单控件的数组,您可以设置一个表单组数组,并且您的 HTML 指令将反映您的表单结构。

    const formGroups: FormGroup[] = myArray.map(x => new FormGroup({
      prop1: new FormControl(x.prop1),
      prop2: new FormControl(x.prop2)
    }));
    this.form = new FormArray(formGroups);
    
    <form [formGroup]="form">
      <div *ngFor="let item of myArray; let i = index"
          [formGroupName]="i"> <!-- <<< bind to the ith form array entry -->
        <input formControlName="prop1" />
        <input formControlName="prop2" />
      </div>
    </form>
    

    绑定到未知属性

    如果您不知道您的对象属性是什么,您可以使用您的对象键创建表单。

    this.form = new FormArray(this.selectedRows.map(row => {
      const formGroup = new FormGroup({});
      Object.keys(row).forEach(key => { // <-- use Object.keys to iterate the object
        formGroup.addControl(key, new FormControl(row[key]));
      });
      return formGroup;
    }));
    

    并从对象键生成您的 HTML

    <form [formGroup]="form">
      <div *ngFor="let row of selectedRows;let i = index">                
        <div [formGroupName]="i">
          <!-- use the keyvalue pipe to iterate the key/value pairs of the object -->
          <span *ngFor="let keyvalue of row | keyvalue">
            <input [formControlName]="keyvalue.key" />
          </span>
        </div>
      </div>
    </form>
    

    演示:https://stackblitz.com/edit/angular-v1jd6x

    【讨论】:

    • 非常感谢库尔特的快速回答!首先,当我清理代码时,我错过了第一个循环的管道,对此感到抱歉。我认为我需要所有控件都不同以在以后读取数据时区分它们,如果我只放置“项目”,则 externalArray 的每个循环都会创建相同的 controlName,不是吗?当我尝试仅放置项目并放弃 [value] 时,我将键名作为输入中的值,例如: TEST1 : TEST1 所以也许我在其他地方做错了?我确实认为我有一个 1-1 映射,因为当我记录它时,我总是拥有与屏幕上的输入一样多的控件
    • 只需将 formControlName 设置为数组的索引就足够了。 stackblitz.com/edit/form-array-template-jsdsgb
    • 我无法更改我的最新评论,为什么,但这里是正确的评论:你好,Kurt。我试着慢慢来,用你的方法重新构建整个东西,但我仍然无法让它像我想要的那样工作。我做了一个stackblitz来显示问题:stackblitz.com/edit/angular-viuopq我有这些错误:错误:找不到路径控制:'0 - > 0'
    • 不清楚你想在这里实现什么。你是说你想创建一个二维的表单控件数组吗?您不能只将表单控件的值设置为数组并期望它适用于文本框。
    • 这就是我没有得到的,我这里有 2 个 for 循环,一个用于检索数组,一个用于迭代它。但不知何故,该值仍然是一个数组。 “selectedRows”数组是一个我无法事先知道其中的大小和对象形状的数组,因为它是基于用户选择的。我需要用这些数据创建一个表单,然后能够检索用户输入的数据。我可能走错路了?
    猜你喜欢
    • 1970-01-01
    • 2018-10-11
    • 2018-03-23
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多