1

I am using Angular 4.3.1 in my project. I am facing issue while generating nested forms. My hierarchy is like this.below code give me error like

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 template ( i am using 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>

where rows is array and each row indicates loop object

[
  {
    "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 and interface 2 all are sections and each have some fields. Now i am getting confused, how i should generate FormGroup for this requirement. When to use FormArray and when to use FormGroup?

Thanks in advance.

7
  • Have a look at this Commented Sep 17, 2018 at 12:34
  • Can you show us your template as well? Commented Sep 17, 2018 at 12:35
  • @ngfelixl added.. I need to create CRUD screen for 2 tables. So fields is going to be dynamic Commented Sep 17, 2018 at 12:36
  • What is row or row.groups? Commented Sep 17, 2018 at 12:40
  • @ngfelixl already added json for row..can you please refresh page? Commented Sep 17, 2018 at 12:41

1 Answer 1

2

This soultion works for me

Added 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>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.