Angular 2 - how to bind to a "dynamic" form field

10,774

Solution 1

You can reference the object using square brackets notation, like this:

<input *ngIf="element.type == 'TEXT_INPUT'" type="text"
[(ngModel)]="model[element.systemName]" />

Solution 2

There's an official documentation page about exactly this:

Dynamic Forms

In it they build a questionnaire / survey form where the list of questions and their types (text, select, radio, etc) are stores in dynamic object (to simulate coming from DB).

The idea is:

  1. ngFor for list of questions
  2. Each question is the same component
  3. The question component has ang ngSwitch that chooses which form control to use

See the live example and source code.

Share:
10,774
Julius
Author by

Julius

Updated on June 15, 2022

Comments

  • Julius
    Julius almost 2 years

    I am building a form generator with Angular 2. The form fields are defined in a datastore somewhere and rendered as a form at runtime by my Angular 2 template. I am trying to setup form binding for the dynamic form, but haven't succeeded so far.

    The first approach I took is below. An input element is rendered conditionally if the current form element ('element') if of type TEXT_INPUT. There is a model class ('model') defined in the backing component and I would like the input form element to bind to model.{{element.systemName}}.

    <input *ngIf="element.type == 'TEXT_INPUT'" type="text"
    [(ngModel)]="model.{{element.systemName}}" 
    class="field-long" placeholder="{{element.label}}" 
    name="{{element.systemName}}" />
    

    This approach doesn't work. {{}} is not allowed as a value to ngModel.

    My second approach didn't work either, because "this" doesn't exist.

    <input (keyup)="updateModel(this)" (blur)="updateModel(this)"
    *ngIf="element.type == 'TEXT_INPUT'" type="text" 
    class="field-long" placeholder="{{element.label}}" 
    name="{{element.systemName}}"/>
    

    Is there some way I can refer to the current form element and send that to the backing component like updateModel(ref.to.current.form.element)?

    It seems that placing #myElementName on the element would create a reference, which would allow me to call updateModel(myElementName). But there again I run into the problem that I need a dynamic name like this #{{element.systemName}}.

    I am completely new to Angular 2, so I am hoping I am overlooking something obvious here.

    Thanks.

  • Julius
    Julius over 7 years
    This is not allowed: Parser Error: Unexpected token [, expected identifier or keyword at column 7 in [model.[element.systemName]] in DynamicFormComponent@16:65 (" </select>
  • Julius
    Julius over 7 years
    That is pretty interesting. Thanks. It the example they JSON.stringify the whole form on submitting to see what is in the form. That seems a good approach as well.
  • Meligy
    Meligy over 6 years
    Thanks. Looks like they changed the format of the URL. It's reachable via clicking "live sample" in the first link. I also updated the 2nd link to match the current URL.
  • Meligy
    Meligy over 6 years
    If that was the reason for the downvote, please check the current version of the answer. Cheers.