Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Angular to output dynamic form fields?

Tags:

angularjs

I want to render a form, based on a dynamic field configuration:

$scope.fields = [
    { title: 'Label 1', type: 'text', value: 'value1'},
    { title: 'Label 2', type: 'textarea', value: 'value2'}
];

This should output something that behaves like:

<div>
    <label>{{field.title}}<br />
        <input type="text" ng-model="field.value"/>
    </label>
</div>
<div>
    <label>{{field.title}}<br />
        <textarea ng-model="field.value" rows="5" cols="50"></textarea>
    </label>
</div>

The simple implementation would be to use if statements to render the templates for each field type. However, as Angular doesn't support if statements, I'm lead to the direction of directives. My problem is understanding how the data binding works. The documentation for directives is a bit dense and theoretical.

I've mocked up a bare bones example of what I try to do here: http://jsfiddle.net/gunnarlium/aj8G3/4/

The problem is that the form fields aren't bound to the model, so the $scope.fields in submit() isn't updated. I suspect the content of my directive function is quite wrong ... :)

Going forward, I need to also support other field types, like radio buttons, check boxes, selects, etc.

like image 386
Gunnar Lium Avatar asked Mar 08 '13 15:03

Gunnar Lium


1 Answers

The first problem you are running into regardless of the directive you are trying to create is using ng-repeat within a form with form elements. It can be tricky do to how ng-repeat creates a new scope.

This directive creates new scope.

I recommend also instead of using element.html that you use ngSwitch instead in a partial template.

<div class="form-row" data-ng-switch on="field.type">
    <div data-ng-switch-when="text">
        {{ field.title }}: <input type="text" data-ng-model="field.value" />
    </div>
    <div data-ng-switch-when="textarea">
        {{ field.title }}: <textarea data-ng-model="field.value"></textarea>
    </div>
</div>

This still leaves you with the problem of modifying form elements in child scope due to ng-repeat and for that I suggest using the ngChange method on each element to set the value when an item has changed. This is one of the few items that I don't think AngularJS handles very well at this time.

like image 82
Ryan O'Neill Avatar answered Sep 29 '22 14:09

Ryan O'Neill