angular 4: 嵌套的表单域:找不到带路径的控件

angular 4: nested form fields : Cannot find control with path

我在我的项目中使用 Angular 4.3.1。我在生成嵌套表单时遇到问题。我的层次结构就像 this.below 代码给我错误

Cannot find control with path: 'interface2 -> interface2Name'(for all fields)

this.myForm = new FormGroup({
  hsrp: new FormGroup({
    name: new FormControl(''),
    description: new FormControl('')
  }),
  interface1: new FormGroup({
    interface1Name: new FormControl(''),
    state: new FormControl('')
  }),
  interface2: new FormGroup({
    interface2Name: new FormControl(''),
    state: new FormControl('')
  })
});

html 模板(我使用的是 ngx-datatable)

<ngx-datatable-row-detail [rowHeight]="175" #myDetailRow>
            <ng-template let-row="row" ngx-datatable-row-detail-template>
                <!--<ng-template let-rowGroup="cuurRowDetail" [ngTemplateOutletContext]="{ cuurRowDetail: (getRowGroups(row) | keyValueUnsorted) }"
                 [ngTemplateOutlet]="selfie" #selfie>-->
                <div class="custom-datatable-row-detail">
                    <form autocomplete="off" class="detail-info-form" [formGroup]="myForm" novalidate (ngSubmit)="save(myForm)">
                        <div class="row no-gutters group-outer-wrapper">
                            <div *ngFor="let group of row.groups; let outerIndex=index;" class="group-wrapper group-col group-col-{{group.length}}">
                                <div class="group-inner-wrapper">
                                    <div class="group-name ml-2 px-2 d-inline-block font-weight-bold">{{group.key | humanize}}</div>
                                    <div class="mt-1" formGroupName="{{group.key}}">
                                        <div *ngFor="let gfield of group.value ; let i=index;" class="form-group clearfix" [style.z-index]="(20 - i)">
                                            <label for="{{gfield.fieldName}}" class="pr-1 mb-0 detail-row-label float-left text-right">
                                                <span class="d-inline-block row-detail-value-middle row-detail-small-font" title="{{gfield.fieldName | humanize}}">{{gfield.fieldName
                                                    | humanize}}</span>
                                            </label>
                                            <span class="d-inline-block float-left row-detail-value-middle row-detail-small-font">: </span>
                                            <div class="pl-1 row-detail-value-wrapper float-left">
                                                <div class="row-detail-value">
                                                    <div *ngIf="currentEditableRowId !== row.id; else paramInput" class="row-detail-value">
                                                        <span class="row-detail-value-text  row-detail-value-middle d-inline-block ellipsis" title="{{gfield.value}}">{{gfield.value}}</span>
                                                    </div>
                                                    <ng-template #paramInput>
                                                        <div class="input-group">
                                                            <input type="text" class="form-control form-control-sm w-100 text-left" placeholder="{{gfield.fieldName | humanize}}" formControlName="{{gfield.fieldName}}"
                                                             name="{{gfield.fieldName}}" />
                                                        </div>
                                                    </ng-template>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
                <!--</ng-template><!-->
            </ng-template>
        </ngx-datatable-row-detail>

其中行是数组,每行表示循环对象

[
  {
    "id": "add-record",
    "name": "",
    "description": "",
    "interface1Name": "",
    "interface2Name": "",
    "groups": [
      {
        "key": "hsrp",
        "value": [
          {
            "fieldName": "id",
            "value": "",
            "group": "hsrp"
          },
          {
            "fieldName": "name",
            "value": "",
            "group": "hsrp"
          },
          {
            "fieldName": "description",
            "value": "",
            "group": "hsrp"
          }
        ]
      },
      {
        "key": "interface1",
        "value": [
          {
            "fieldName": "interface1Name",
            "value": "",
            "group": "interface1"
          },
          {
            "fieldName": "state",
            "value": "",
            "group": "interface1"
          }
        ]
      },
      {
        "key": "interface2",
        "value": [
          {
            "fieldName": "interface2Name",
            "value": "",
            "group": "interface2"
          },
          {
            "fieldName": "state",
            "value": "",
            "group": "interface2"
          }
        ]
      }
    ]
  },
  {
    "id": "100",
    "name": "name-trst",
    "interface1Name": "interface1Name-trst",
    "interface2Name": "interface2Name-trst",
    "description": "description-trst",
    "groups": [
      {
        "key": "hsrp",
        "value": [
          {
            "fieldName": "id",
            "value": "100",
            "group": "hsrp"
          },
          {
            "fieldName": "site",
            "value": "lon",
            "group": "hsrp"
          },
          {
            "fieldName": "name",
            "value": "name-trst",
            "group": "hsrp"
          },
          {
            "fieldName": "description",
            "value": "description-trst",
            "group": "hsrp"
          }
        ]
      },
      {
        "key": "interface1",
        "value": [
          {
            "fieldName": "instance1Name",
            "value": "esxi.lon",
            "group": "interface1"
          },
          {
            "fieldName": "interface1Name",
            "value": "interface1Name-trst",
            "group": "interface1"
          },
          {
            "fieldName": "state",
            "value": "state-trst",
            "group": "interface1"
          }
        ]
      },
      {
        "key": "interface2",
        "value": [
          {
            "fieldName": "instance2Name",
            "value": "esxi.lon",
            "group": "interface2"
          },
          {
            "fieldName": "interface2Name",
            "value": "interface2Name-trst",
            "group": "interface2"
          },
          {
            "fieldName": "state",
            "value": "trst",
            "group": "interface2"
          }
        ]
      }
    ],
    "$$index": 0
  },
  {
    "id": "101",
    "name": "name-trst22",
    "interface1Name": "interface1Name-trst22",
    "interface2Name": "interface2Name-trst22",
    "description": "description-trst222",
    "groups": [
      {
        "key": "hsrp",
        "value": [
          {
            "fieldName": "id",
            "value": "101",
            "group": "hsrp"
          },
          {
            "fieldName": "site",
            "value": "lon",
            "group": "hsrp"
          },
          {
            "fieldName": "name",
            "value": "name-trst22",
            "group": "hsrp"
          },
          {
            "fieldName": "description",
            "value": "description-trst222",
            "group": "hsrp"
          }
        ]
      },
      {
        "key": "interface1",
        "value": [
          {
            "fieldName": "instance1Name",
            "value": "esxi.lon",
            "group": "interface1"
          },
          {
            "fieldName": "interface1Name",
            "value": "interface1Name-trst22",
            "group": "interface1"
          },
          {
            "fieldName": "state",
            "value": "state-trst22",
            "group": "interface1"
          }
        ]
      },
      {
        "key": "interface2",
        "value": [
          {
            "fieldName": "instance2Name",
            "value": "esxi.lon",
            "group": "interface2"
          },
          {
            "fieldName": "interface2Name",
            "value": "interface2Name-trst22",
            "group": "interface2"
          },
          {
            "fieldName": "state",
            "value": "trst222",
            "group": "interface2"
          }
        ]
      }
    ],
    "$$index": 1
  }
]

hsrp , interface1 和 interface 2 都是部分,每个部分都有一些字段。现在我很困惑,我应该如何为这个要求生成 FormGroup。什么时候用FormArray,什么时候用FormGroup

提前致谢。

这个灵魂适合我

已添加FormArray

this.formGroupObj = new FormGroup({
      hsrp: new FormArray([
        new FormGroup({
          name: new FormControl('asdasd'),
          description: new FormControl('sadasd')
        })
      ]),
      interface1: new FormArray([
        new FormGroup({
          interface1Name: new FormControl('dsad'),
          state: new FormControl('asdasd')
        })
      ]),
      interface2: new FormArray([
        new FormGroup({
          interface2Name: new FormControl('asda'),
          state: new FormControl('asdsad')
        })
      ])
    });

html;

<form autocomplete="off" class="detail-info-form" [formGroup]="formGroupObj" novalidate>
    <div class="row no-gutters group-outer-wrapper">
        <div *ngFor="let group of row.groups; let outerIndex=index;" class="group-wrapper group-col group-col-{{group.length}}">
            <div class="group-inner-wrapper">
                <div class="group-name ml-2 px-2 d-inline-block font-weight-bold">{{group.key | humanize}}</div>
                <div class="mt-1" [formArrayName]="group.key">
                    <div *ngFor="let ctrl of formGroupObj.get(group.key)['controls']; let i = index" [formGroupName]="i">
                        <div *ngFor="let gfield of group.value ; let i=index;">
                            <div *ngIf="nonEditableColumns.indexOf(gfield.fieldName) === -1"  class="form-group clearfix" [style.z-index]="(20 - i)">
                                <label for="{{gfield.fieldName}}" class="pr-1 mb-0 detail-row-label float-left text-right">
                                    <span class="d-inline-block row-detail-value-middle row-detail-small-font" title="{{gfield.fieldName | humanize}}">{{gfield.fieldName
                                        | humanize}}</span>
                                </label>
                                <span class="d-inline-block float-left row-detail-value-middle row-detail-small-font">: </span>
                                <div class="pl-1 row-detail-value-wrapper float-left">
                                    <div class="row-detail-value">
                                        <div *ngIf="currentEditableRowId !== row.id; else paramInput" class="row-detail-value">
                                            <span class="row-detail-value-text  row-detail-value-middle d-inline-block ellipsis" title="{{gfield.value}}">{{gfield.value}}</span>
                                        </div>
                                        <ng-template #paramInput>
                                            <div class="input-group">
                                                <input type="text" class="form-control form-control-sm w-100 text-left" placeholder="{{gfield.fieldName | humanize}}"
                                                    [formControlName]="gfield.fieldName" name="{{gfield.fieldName}}" />
                                            </div>
                                        </ng-template>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>