Dynamically Bound Inputs with Angular (1.6)

As I continue to learn angular, I have found myself moving towards more abstract/dynamic programming with javascript. That is, relying on a languages features to alter the functionality of piece of code through data. Recently I’ve discovered the need for dynamically bound inputs – or input fields that bind to a scope during runtime and are unknown at “compile” time. The following provides a basic approach towards that end.

First, some basic data testing. Our $scope will contain a model for us to bind to, and we’ll display the values with some simple HTML.

<div class="message">
    <h1>Title: {{ entity.title }} </h1>
    <pre>{{ entity.description }}</pre>
</div>

Next, we’ll need to provide a way of rendering out our input fields. Through some research of [at first] $compile and ngInclude, I have discovered a brutally simple way to include directive-like structures.

<div class="field-panel">
    <div ng-repeat="f in fields">
        <div ng-include="getTemplate(f.type)" onload="field = f"></div>
    </div>
</div>

Because of some oddities in how ngInclude works, a simple method is required to concatenate the values. Admittedly, these can be passed in via the JSON data you are about to see, but I wanted to push the limits of what can possibly be made into a calculated value.

$scope.getTemplate = function (type) {
    return 'templates/' + type + '.htm';
};

Our JSON is provided as a constant, but may easily be loaded through some other means such as an HTTP request to a server resource. For the simplicity of the demo, using a constant is an obvious choice.

$scope.fields = [
    {
        name: 'Title',
        key: 'title',
        type: 'singleline-text',
        __system: {
            label: 'Item Title',
            placeholder: 'Give your todo a title'
        },
        binding: 'title'
    },
    {
        name: 'Item Description',
        key: 'description',
        type: 'singleline-text',
        __system: {
            label: 'Description',
            placeholder: 'Tell us what you want to do'
        },
        binding: 'description'
    }
];

And lastly, the HTML source for the template, maintained in singleline-text.htm.

<div>
    <label>{{ field.__system.label }}</label>
    <input type="text" 
        placeholder="{{ field.__system.placeholder }}" 
        ng-model="entity[field.binding]"
    />
</div>

When all is said and done, we have the following browser output!

Dynamic Fields Output
©2018 John Sedlak. All Rights Reserved.