【问题标题】:How to create a directive with a dynamic template in AngularJS?如何在 AngularJS 中使用动态模板创建指令?
【发布时间】:2013-01-29 12:23:34
【问题描述】:

如何使用动态模板创建指令?

'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>

这就是我现在所拥有的,它可以正确显示标签。但是,我不确定如何在模板中附加额外的 HTML。或者将 2 个模板合并为 1 个。

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    一种方法是在指令中使用模板函数:

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

    【讨论】:

      【解决方案2】:

      我也遇到了同样的情况,我的完整解决方案已发布here

      基本上我就是这样在指令中加载模板

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

      然后根据maxLengthrequired的值,我可以动态加载2个模板之一,如果需要,一次只显示一个。

      我希望它有帮助。

      【讨论】:

        【解决方案3】:

        如果你想在动态模板中使用 AngularJs 指令,你可以使用那些答案,但这里有更多 专业合法 语法。你可以使用 templateUrl 不仅可以使用单个值。您可以将其用作函数,它以 url 的形式返回值。该函数有一些参数,您可以使用它们。

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

        【讨论】:

        • 这不允许在某些数据更改时动态更改内容。例如,我是一个数据类型属性来指示要使用的模板 - 然后当用户切换类型时,我需要一个不同的模板。
        【解决方案4】:

        您应该使用“ng-switch”指令将您的开关移动到模板中:

        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);
                }
            };
        });
        

        可以这样使用:

        <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="me@example.com"></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>
        

        【讨论】:

          【解决方案5】:

          我设法解决了这个问题。以下是链接:

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

          具体文件为:

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

          dynamicTemplate 指令承载动态模板,该模板在范围内传递,承载元素的行为与其他原生角度元素一样。

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

          【讨论】:

            【解决方案6】:

            我已经使用 $templateCache 来完成类似的事情。我将几个 ng 模板放在一个 html 文件中,我使用指令的 templateUrl 引用该文件。这确保 html 可用于模板缓存。然后我可以简单地通过 id 选择来获得我想要的 ng-template。

            模板.html:

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

            指令:

            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);
                    }
                };
            }]);
            

            【讨论】:

            • 好动作,齐姆!稍微简化一下:$templateCache 在链接函数中可用,所以你不需要 getTemplate 函数
            • @zim 但是如何动态传递 id?
            • +1 表示$compile(element.contents())。快疯了,因为我不知道.contents()ìn $compile。 (当然是无限循环调用我的指令)
            • @JannieT,我有一个单独的getTemplate() 函数只是为了保持链接函数的干净。我可以内联它,是的,但是如果需要大量代码来解析数据并确定要使用哪个模板,它可能会掩盖链接函数的重要最后两行。而且我还是小而单一的函数方法的粉丝。
            • 如果您已经嵌入了不想丢失的内容,这可能会中断。
            【解决方案7】:

            有类似的需求。 $compile 完成这项工作。 (不完全确定这是否是“THE”方式,仍在通过角度工作)

            http://jsbin.com/ebuhuv/7/edit - 我的探索测试。

            需要注意的一点(根据我的示例),我的一个要求是,一旦您单击保存,模板将根据 type 属性进行更改,并且模板非常不同。所以虽然,你得到了数据绑定,如果需要一个新的模板,你将不得不重新编译。

            【讨论】:

            • 您的示例似乎无法正常工作。你能跟进吗?
            • 编辑:让它工作,看起来它是引导程序。更新链接:jsbin.com/wikocaru/2/edit
            • 答案应该包括完整的示例和代码,而不是稍后会被破坏的链接。
            • 会很高兴看到在接受的答案中的小sn-p代码。
            猜你喜欢
            • 2015-03-17
            • 1970-01-01
            • 2017-05-27
            • 1970-01-01
            • 2013-01-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多