Display dynamically defined inputs


#1

I would like to download a form definition from a server (in JSON format), parse, it and then spit out the HTML for the form on a page.

Where possible I would like to use existing Ionic components (e.g. ion-col, ion-input) but I am not having too much luck with inputs.

When I’m generating the form, an example of the input code would be…

return `<ion-list><ion-item>
    <ion-label fixed>${this.label}</ion-label>
    <ion-input 
        
        ${this.id ? 'id="' + this.id + '"' : ''}
        ${this.class ? 'class="' + this.class + '"' : ''}
        ${this.required ? "required":""}></ion-input>
    </ion-item></ion-list>`;

But understandably the app isn’t “parsing” the ion-input and displaying what I would expect, right now I just get the ion-input shell, but no actual HTML input.

In Angular 1 / Ionic 1 I was using $templateCache ( https://docs.angularjs.org/api/ng/service/$templateCache ) which processed the provided input and gave me what I required.

Is there something similar I can do for Angular 2 / Ionic 2?

Cheers!


#2

What I would do is to have the template be a big ngFor with a bunch of conditional elements based on the types of the various components, backed by a heterogeneous array of form definitions in your component. Something like:

<template ngFor let-field [ngForOf]="fields">
  <template [ngIf]="field.flavor == 'textinput'">
    <ion-item>
      <ion-label>{{field.label}}</ion-label>
      <ion-input [(ngModel)]="field.value"></ion-input>      
    </ion-item>
  </template>
  <template [ngIf]="field.flavor == 'checkbox'">
    <ion-item>...</ion-item>
  </template>
  ...
</template>

#3

Cheers Rapropos, that’d work great for a flat list format.

Let’s say I have a stacked format with nested elements. E.g

ion-grid > ion-row > ion-col > ion-list > [ion-input, ion-input, ion-input, ion-input]

Would that be possible in some clever way?


#4

The clever way would involve recursion, which probably won’t work due to circular dependencies. If you’ve only got one level of nesting (which should probably be true if only to avoid a gnarly UX), you could replicate the big switch inside a ‘list’ flavor component like so:

<template [ngIf]="field.flavor == 'list'">
  <template ngFor let-child [ngForOf]="field.children">
    ... all the other non-list options in the upper level repeated ...
  </template>
</template>