Angular 4 Dynamic form with nested groups

ぐ巨炮叔叔 提交于 2019-12-04 14:58:32

To support unlimited number of nested group i would use markup like:

<ng-container [formGroup]="form">
  <ng-container 
     *ngTemplateOutlet="formItemTemplate; context:{ $implicit: 0, group: form }">
  </ng-container>

  <ng-template #formItemTemplate let-i let-group="group">
      <fieldset *ngIf="i < pathSegments.length - 1" class="form-group">
        <legend>{{ pathSegments[i] }}</legend>
        <ng-container 
          *ngTemplateOutlet="formItemTemplate; 
          context:{ $implicit: i + 1, group: group.get(pathSegments[i]) }">
        </ng-container>
      </fieldset>

      <div *ngIf="i + 1 === pathSegments.length" class="form-control" [formGroup]="group">
        <label>{{pathSegments[pathSegments.length - 1]}}</label>
        <input [formControlName]="pathSegments[pathSegments.length - 1]"/>
      </div>
  </ng-template>
</ng-container>

Plunker Example

As @yurzui mentioned in comment, the problem occurs because the FormControlName directive uses @Optional() @Host() @SkipSelf() parent: ControlContainer to find parent formGroup.

Thus, the following code works fine, but contains code duplicates and supports a limited number of nested groups.

@Component({
  selector: 'form-item',
  template: `
    <ng-container [formGroup]="form">

      <div class="form-control" *ngIf="pathSegments.length === 1">
        <label>{{pathSegments[pathSegments.length - 1]}}</label>
        <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/>
      </div>

      <ng-container *ngIf="pathSegments.length === 2" [formGroupName]="pathSegments[0]">
        <div class="form-control">
          <label>{{pathSegments[pathSegments.length - 1]}}</label>
          <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/>
        </div>
      </ng-container>

      <ng-container *ngIf="pathSegments.length === 3" [formGroupName]="pathSegments[0]">
        <ng-container [formGroupName]="pathSegments[1]">
          <div class="form-control">
            <label>{{pathSegments[pathSegments.length - 1]}}</label>
            <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/>
          </div>
        </ng-container>
      </ng-container>

      <ng-container *ngIf="pathSegments.length === 4" [formGroupName]="pathSegments[0]">
        <ng-container [formGroupName]="pathSegments[1]">
          <ng-container [formGroupName]="pathSegments[2]">
            <div class="form-control">
              <label>{{pathSegments[pathSegments.length - 1]}}</label>
              <input type="text" [formControlName]="pathSegments[pathSegments.length - 1]"/>
            </div>
          </ng-container>
        </ng-container>
      </ng-container>
    </ng-container>
  `,
})

Any ideas how to improve that?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!