I came across the need for this recently and it was pretty easy to achieve so this should be a quick one.
In my case I had to build a dynamic form from JSON. An endpoint would send me JSON representing a form with a seemingly random amount of fields – of varying types and also some other conditional behaviour which I will spare from hearing about here.
Heres an example of the kind of thing I might expect to see – simplified a bit (a lot) for sake of example.
[ { type: 'text', data: '', label: 'Name' }, { type: 'email', data: '', label: 'Email address' }, { type: 'select', data: '', label: 'Animal', options: ['Cat','Dog','Fish'] }]
There were actually about 5 other types I would be sent too, and with extra functionality – I only tell you this so you don’t think this approach is a bit heavy-handed for something as simple as this example.
I decided I wanted to use a single directive for these fields, but seeing as each one needed to be be represented differently I wanted each type to have its own template. The directive is pretty simple:
angular.module('exampleApp').directive('dynamicField', function() { return { restrict: 'E', replace: true, scope: { fieldData: '=' }, link: function(scope, element, attrs) { // Function returns the correct template for each field. scope.getTemplateUrl = function() { var type = scope.fieldData.type || 'text'; return 'dynamic-fields/dynamic-field-'+type+'.html'; } }, template: '<div class="dynamic-field" ng-include="getTemplateUrl()"></div>' };});
So assuming I have the fields on the scope of my controller I would loop through them like so:
<form> <dynamic-field field-data="fieldData" ng-repeat="fieldData in fields"></dynamic-field> <input type="submit" value="Submit" /></form>
So this provides the fieldData to the directive, which contains the type (any anything else the field requires) and the directive used the correct template. Heres an example of the dynamic-field-text.html template:
<label>{{fieldData.label}}</label><input type="text" ng-model="fieldData.data" />
And the dynamic-field-select.html template:
<label>{{fieldData.label}}</label><select ng-model="fieldData.data" ng-options="o as o for o in fieldData.options"> <option value="">-- Pick one --</option></select>
Pretty simple huh!