[angularjs] How to create a directive with a dynamic template in AngularJS?

How can I create a directive with a dynamic template?

'use strict';

app.directive('ngFormField', function($compile) {
return {
    transclude: true,
    scope: {
        label: '@'
    },
    template: '<label for="user_email">{{label}}</label>',
    // append
    replace: true,
    // attribute restriction
    restrict: 'E',
    // linking method
    link: function($scope, element, attrs) {
        switch (attrs['type']) {
            case "text":
                // append input field to "template"
            case "select":
                // append select dropdown to "template"
        }
    }
  }
});
<ng-form-field label="First Name" type="text"></ng-form-field>

This is what I have right now, and it is displaying the label correctly. However, I'm not sure on how to append additional HTML to the template. Or combining 2 templates into 1.

This question is related to angularjs angularjs-directive

The answer is


I managed to deal with this problem. Below is the link :

https://github.com/nakosung/ng-dynamic-template-example

with the specific file being:

https://github.com/nakosung/ng-dynamic-template-example/blob/master/src/main.coffee

dynamicTemplate directive hosts dynamic template which is passed within scope and hosted element acts like other native angular elements.

scope.template = '< div ng-controller="SomeUberCtrl">rocks< /div>'

You should move your switch into the template by using the 'ng-switch' directive:

module.directive('testForm', function() {
    return {
        restrict: 'E',
        controllerAs: 'form',
        controller: function ($scope) {
            console.log("Form controller initialization");
            var self = this;
            this.fields = {};
            this.addField = function(field) {
                console.log("New field: ", field);
                self.fields[field.name] = field;
            };
        }
    }
});

module.directive('formField', function () {
    return {
        require: "^testForm",
        template:
            '<div ng-switch="field.fieldType">' +
            '    <span>{{title}}:</span>' +
            '    <input' +
            '        ng-switch-when="text"' +
            '        name="{{field.name}}"' +
            '        type="text"' +
            '        ng-model="field.value"' +
            '    />' +
            '    <select' +
            '        ng-switch-when="select"' +
            '        name="{{field.name}}"' +
            '        ng-model="field.value"' +
            '        ng-options="option for option in options">' +
            '        <option value=""></option>' +
            '    </select>' +
            '</div>',
        restrict: 'E',
        replace: true,
        scope: {
            fieldType: "@",
            title: "@",
            name: "@",
            value: "@",
            options: "=",
        },
        link: function($scope, $element, $attrs, form) {
            $scope.field = $scope;
            form.addField($scope);
        }
    };
});

It can be use like this:

<test-form>
    <div>
        User '{{!form.fields.email.value}}' will be a {{!form.fields.role.value}}
    </div>
    <form-field title="Email" name="email" field-type="text" value="[email protected]"></form-field>
    <form-field title="Role" name="role" field-type="select" options="['Cook', 'Eater']"></form-field>
    <form-field title="Sex" name="sex" field-type="select" options="['Awesome', 'So-so', 'awful']"></form-field>
</test-form>

I have been in the same situation, my complete solution has been posted here

Basically I load a template in the directive in this way

var tpl = '' + 
    <div ng-if="maxLength" 
        ng-include="\'length.tpl.html\'">
    </div>' +
    '<div ng-if="required" 
        ng-include="\'required.tpl.html\'">
    </div>';

then according to the value of maxLength and required I can dynamically load one of the 2 templates, only one of them at a time is shown if necessary.

I heope it helps.


If you want to use AngularJs Directive with dynamic template, you can use those answers,But here is more professional and legal syntax of it.You can use templateUrl not only with single value.You can use it as a function,which returns a value as url.That function has some arguments,which you can use.

http://www.w3docs.com/snippets/angularjs/dynamically-change-template-url-in-angularjs-directives.html


i've used the $templateCache to accomplish something similar. i put several ng-templates in a single html file, which i reference using the directive's templateUrl. that ensures the html is available to the template cache. then i can simply select by id to get the ng-template i want.

template.html:

<script type="text/ng-template" id=“foo”>
foo
</script>

<script type="text/ng-template" id=“bar”>
bar
</script>

directive:

myapp.directive(‘foobardirective’, ['$compile', '$templateCache', function ($compile, $templateCache) {

    var getTemplate = function(data) {
        // use data to determine which template to use
        var templateid = 'foo';
        var template = $templateCache.get(templateid);
        return template;
    }

    return {
        templateUrl: 'views/partials/template.html',
        scope: {data: '='},
        restrict: 'E',
        link: function(scope, element) {
            var template = getTemplate(scope.data);

            element.html(template);
            $compile(element.contents())(scope);
        }
    };
}]);

One way is using a template function in your directive:

...
template: function(tElem, tAttrs){
    return '<div ng-include="' + tAttrs.template + '" />';
}
...