Trying to make a dinamic form

Here’s how I would do this. This assumes that there is only one layer of nesting, and that all inputs are text. Both of those assumptions could be relaxed without too much additional effort. I’ve used a more complex version of this basic design to implement a markdown renderer in Ionic.

interface Field {
  name: string;
  label?: string;
  control?: FormControl;
}

interface Block {
  name: string;
  label?: string;
  fields: Field[];
  control?: FormGroup;
}

type Schema = Block[];

export class HomePage {
  fg: FormGroup;
  schema: Schema = [
    {
      name: 'info',
      label: '基本情報',
      fields: [{name: 'id'}, {name: 'name', label: '名前'}]
    },
    {
      name: 'location',
      fields: [{name: 'street'}, {name: 'neighborhood'}]
    }
  ];

  constructor() {
    this.fg = new FormGroup({});
    this.schema.forEach(block => {
      this.fg.addControl(block.name, block.control = this.groupify(block.fields));
    });
  }

  private groupify(fields: Field[]): FormGroup {
    let rv = new FormGroup({});
    fields.forEach(field => {
      rv.addControl(field.name, field.control = new FormControl());
    });
    return rv;
  }
}
<ion-content>
    <ion-list>
        <ng-container *ngFor="let block of schema">
            <ion-item-divider>{{block.label || block.name}}</ion-item-divider>
            <ion-item *ngFor="let field of block.fields">
                <ion-label [innerText]="field.label || field.name"></ion-label>
                <ion-input [formControl]="field.control"></ion-input>
            </ion-item>
        </ng-container>
    </ion-list>

    <div><pre><code>
        {{fg.value | json}}
    </code></pre>
    </div>
</ion-content>

As you can see, the optional label property for fields and blocks can be used to display human-readable labels (localized if desired) aside from the name property used internally, and here is how to gracefully fall back to the name if there is no label. The automatically-updating <div> at the bottom shows what you should be able to send directly to a backend API with virtually no extra work.

The Schema object could be serialized/deserialized from JSON.

1 Like