1

I'm trying to generate dynamic form recursively from JSON schema, but i'm struggling with form control not being found. Here is Code Examples.

I get this error

ERROR Error: Cannot find control with name: 'individualPerson'

I tried different approaches but there is still a problem. i know i miss something so please help. any help will be appreciated.

Problem occurs on the template side

app.components.ts

export class AppComponent {
  filterForm: FormGroup;
  filterFields: any[];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.filterFields = [
      {
        key: "common",
        title: "main fields",
        group: [
          {
            key: "createdAt",
            title: "Create Date",
            type: "date"
          },
          {
            key: "individualPerson",
            title: "Physical Person",
            group: [
              {
                key: "firstname",
                title: "First Name",
                type: "text"
              },
              {
                key: "lastname",
                title: "Last Name",
                type: "text"
              },
              {
                key: "phone",
                title: "Phone Number",
                type: "text"
              },
              {
                key: "citizenshipCountry",
                title: "Country",
                type: "text"
              }
            ]
          },
          {
            key: "legalPerson",
            title: "Legal Person",
            group: [
              {
                key: "brandname",
                title: "Brand Name",
                type: "text"
              },
              {
                key: "fullname",
                title: "Full Name",
                type: "text"
              },
              {
                key: "phone",
                title: "Phone",
                type: "text"
              },
              {
                key: "registrationCountry",
                title: "Country",
                type: "text"
              }
            ]
          }
        ]
      }
    ];

    this.filterForm = this.generateFilterForm();
  }

  generateFilterForm(): FormGroup {
    const baseForm = this.fb.group({});
    this.filterFields.forEach(field => {
      baseForm.addControl(field.key, this.generateFormGroup(baseForm, field));
    });
    console.log(baseForm);
    return baseForm;
  }

  generateFormGroup(baseForm: FormGroup, field): FormGroup {
    if (field.group) {
      const formGroup = this.fb.group({});
      field.group.forEach(item => {
        formGroup.addControl(item.key, this.generateFormGroup(formGroup, item));
      });
      return formGroup;
    } else {
      baseForm.addControl(field.key, new FormControl(""));
    }
    return baseForm;
  }
}

app.component.html

<form [formGroup]="filterForm" class="filter-form">
    <ng-template #recursiveList let-filterFields let-fromGroup="fromGroup">
        <ng-container *ngFor="let item of filterFields">
            <ng-container *ngIf="item.group; else default;">
                <p>{{item.title}}</p>
                <div class="row pb-4" [formGroupName]="item.key">
                    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.group, fromGroup: {name: item.key} }"></ng-container>
                </div>
            </ng-container>
            <ng-template #default>       
                <div class="col-md-3">
                    <div class="form-group" [formGroupName]="fromGroup.name">
                        <input [type]="item.type" [formControlName]="item.key" [placeholder]="item.title" [name]="item.key" />
                    </div>
                </div>
            </ng-template>
        </ng-container>
    </ng-template>
    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: filterFields }"></ng-container>
</form>

1 Answer 1

2

there're some strange in your code

1.-Change your function generateFormGroup to return a simple FormControl in case field.group=false

generateFormGroup(baseForm: FormGroup, field): FormGroup|FormControl {
    if (field.group) {
      const formGroup = this.fb.group({});
      field.group.forEach(item => {
        formGroup.addControl(item.key, this.generateFormGroup(formGroup, item));
      });
      return formGroup;
    }
      return new FormControl("");
  }}

In recursive .html pass to the template the formGroup and use [formControl] and [formGroup] (I can not get it using formControlName and formGroupName). Some like -see that I changed a few where put the formGroup-

<form *ngIf="filterForm" [formGroup]="filterForm" class="filter-form">
    <ng-container *ngTemplateOutlet="recursiveList; 
          context:{ $implicit: filterFields,formGroup:filterForm }">
    </ng-container>
</form>

<ng-template #recursiveList let-filterFields let-formGroup="formGroup">
    <div class="form-group">
        <ng-container *ngFor="let item of filterFields">
            <p>{{item.title}}</p>
            <ng-container *ngIf="item.group; else default;">
                <div class="row pb-4">
                    <div [formGroup]="formGroup.get(item.key)">
                        <ng-container
                            *ngTemplateOutlet="recursiveList; 
                              context:{ $implicit: item.group, formGroup: formGroup.get( item.key)}">
                        </ng-container>
                    </div>
                </div>
            </ng-container>
            <ng-template #default>
                <div class="col-md-3">
                    <input [type]="item.type" [formControl]="formGroup.get(item.key)" 
                           [placeholder]="item.title" [name]="item.key" />
                </div>
            </ng-template>
        </ng-container>
    </div>
</ng-template>

You can see in the stackblitz

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.