首页 > 解决方案 > 表单组对象绑定和验证的角度反应表单模块数组

问题描述

我有一个结构有点复杂的反应形式。我正在努力为表单中的一组表单组对象创建表单控件和验证。

之前已经在这里提出过类似的问题,但我无法找到有关如何绑定到表单组数组的任何答案。

父表单组Record具有顶级属性,然后是表单组对象的嵌套数组Items

每个项目都有属性“标题”和“描述”。标题和描述需要控制和验证。我不一定知道表单上需要多少项目,这取决于使用默认值初始化表单时每个“记录”有多少“项目”。

这是一个堆栈闪电战: https ://stackblitz.com/edit/angular-nkhgsj

以下是代码中的一些片段:

示例数据:

  // Placeholder to emulate data from an API response
  recordAPIResponse =
    {
      "ID": 12345,
      "Items": [
        {
          "Title": "Example title 1",
          "Description": "Example description 1"
        },
        {
          "Title": "Example title 2",
          "Description": "Example description 2"
        },
        {
          "Title": "Example title 3",
          "Description": "Example description 3"
        }
      ]
    };

表单使用从 API 响应返回的记录值进行初始化。

  private initRecordForm(record: Record) {

    // Create items controls with validations
    const itemsCtrls = this.createItemsCtrls(record.Items);

    const recordForm = this.fb.group({
      ID: [record.ID, Validators.compose([
        Validators.minLength(3),
        Validators.maxLength(10),
        Validators.pattern(/^[0-9]*$/)
      ])],
      items: itemsCtrls

    });

    return recordForm;

  }

“项目”控件已预先填充,然后在初始化时放入父表单组。

  // Create a form control for each object in Items array
  private createItemsCtrls(items: Item[]) {

    // Initilize an empty form array
    let formArrayCtrls = this.fb.array([]);

    // Iterate each value
    if (items && items.length > 0) {
      items.forEach(item => {
        // Create a new form control for each array value and push to form array
        formArrayCtrls.push(
          this.fb.group({
            Title: [item.Title, Validators.compose([
              Validators.minLength(5),
              Validators.maxLength(10),
              Validators.pattern(/^[0-9A-Za-z]*$/)
            ])],
            Description: [item.Description, Validators.compose([
              Validators.minLength(1),
              Validators.maxLength(20),
              Validators.pattern(/^[0-9A-Za-z]*$/)
            ])]
          })
        );
      });
    }

    console.log(formArrayCtrls);
    return formArrayCtrls;

  }

这是可行的,表单组是使用表单组对象的嵌套数组创建的。

但是,我现在不知道将表单组对象的嵌套数组绑定到模板、捕获最新值并执行验证。

<form [formGroup]="recordForm" (submit)="onSubmit()">
  <div>
    <label>ID: </label>
    <input formControlName="ID">
  </div>
  <div formArrayName="Items">
    <ng-container *ngFor="let item of record.Items">
      <label>Title: </label>
      <input formControlName="Title">
      <label>Description: </label>
      <input formControlName="Description">
      <br />
    </ng-container>
  </div>
  <button type="submit">Submit</button>
</form>

错误信息:

ERROR Error: Cannot find control with path: 'Items -> Title'

标签: angularreactive-forms

解决方案


所以你的表单数组实际上是一个表单组数组,每个表单组的“名称”是它在数组中的索引,所以你需要让 Angular 知道索引才能访问它:

<ng-container
  *ngFor="let item of record.Items; let i = index"
  [formGroupName]="i">
</ng-container>

闪电战链接:https ://stackblitz.com/edit/angular-nznpfj?file=src/app/app.component.html


推荐阅读