AngularJS - 模板中的指令

时间:2014-08-01 11:43:43

标签: javascript jquery angularjs angularjs-directive

我试图找到动态创建使用指令创建的元素的子内容的最佳方法。

举一个简单的例子,假设我有指示说创建一个基本的div子元素。

<div mydirective></div>

结果

<div mydirective><div></div></div>

该指令可能类似于:

angular.module('demo', [])
.directive('mydirective', function() {
    return {
        restrict: 'A',           
        template:   '<div></div>'
    }
})

然后说我想创建一个&#34;扩展&#34;这个指令使内部div变为蓝色。因为我不知道我将来需要哪些扩展,所以我不想切换模板或绑定任何特定属性。

我不知道这些是可能的,或者正常方法是什么......但是你可以

1)向父元素添加一个附加指令(像css一样),即

<div mydirective mybluedirective></div>

mybluedirective寻找内部div并操纵它?

2)你可以在模板中动态包含指令,例如

<div mydirective subdirective="mybluedirective"></div>

angular.module('demo', [])
.directive('mydirective', function() {
    return {
        restrict: 'A',           
        template:   '<div [[[THE SUBDIRECTIVE PROPERTY FROM SCOPE??]]></div>'
    }
})

有没有办法拦截预编译以注入指令?

第三个选项,因为我已经准备好使用工厂和继承的类来完成指令的工作,但这似乎有点过头了。

我猜测有一种我不知道的简单方法,任何建议都值得赞赏

编辑:

我认为我尝试做的是动态修改模板,以便在编译之前使用另一个指令。

3 个答案:

答案 0 :(得分:3)

选项1 - 动态修改模板

如果要在编译之前动态修改模板,可以使用模板函数:

HTML:

<div mydirective subdirective="mybluedirective"></div>

JS:

angular.module('demo', [])
.directive('mydirective', function() {
    return {
        restrict: 'A',           
        template:   function(element, attr) { 
             return '<div ' + attr.subdirective + '></div>'
        }
    }
})

选项2 - 对模板的编程访问

或者,您可以公开mydirective mybluedirective可以使用的API。此解决方案需要mydirective来延迟编译(因为模板将手动编译),并且更多地考虑mydirective的设计和意图如何扩展:

<强> HTML

<div mydirective mybluedirective></div>

<强> JS

angular.module('demo', [])
.directive('mydirective', function($compile) {

    return {
        restrict: 'A',           
        template:   '<div></div>',
        // we want a child scope so that we don't pollute the parent scope
        scope: true,
        controller: function($scope, $element) {
            var attrs = {};
            // expose an API to add attributes dynamically
            this.addAttr = function(attr, value) {
                attrs[attr] = value;
            }
            $scope.attrs = attrs;
        },
        compile: function(element, attr) {
            // save the template
            var template = element.find('div');

            // empty the contents so it is not compiled (we're manually compiling during link)
            element.empty();

            return function(scope, element, attr) {
                // add the attributes to the template
                angular.forEach($scope.attrs, function(value, key) {
                    template.addAttr(key, value);
                }
                // add the template to the DOM
                element.append(template);

                // link the template to scope
                $compile(template)(scope);
            }

        }

    }
})
.directive('mybluedirective', function() {
     return {
          restrict: 'A',
          require: 'mydirective',
          link: function(scope, element, attr, mydirectiveController) {
               mydirectiveController.addAttr('ng-class','blue');
          }
     }
});

答案 1 :(得分:2)

我使用ng-class绑定到指令中的公开变量。您还需要添加范围,如果要设置默认值,则需要添加控制器或链接功能。

以下是一个快速示例:

angular.module('demo', [])
.directive('mydirective', function() {
    return {
        restrict: 'A',           
        // add the ng-class to the template.  It binds to options.someClass
        template:   '<div ng-class="options.someClass"></div>',
        // give the directive its own Scope with an input object named options
        scope: {
            options : "="
        },  
        // Give the directive a controller
        controller: function($scope) {
            //  This is an init function to default the input objects 
             this.onInit = function(){
                   //  If the options object does not exist; create it 
                    if(!$scope.options){
                        $scope.options = {};
                    }
                   //  If our custom someClass variable doesn't exist; then give it a default value
                    if(!$scope.options.someClass){
                        $scope.options.someClass= "defaultClass";
                    }            }
             // call the onInit() function to set up the defaults
             onInit();
        }
    }
})

然后我还提供了一个CSS作为包含默认样式的指令的一部分。你可以相对容易地将它付诸实践。在您的控制器中创建我们的选项对象:

myDirectiveOptions = {
   someClass = 'myCustomClass';
}

在您看来,请执行以下操作:

<div mydirective options="myDirectiveOptions"></div>

我发现这很简单,但非常强大。


使用这种方法;动态地改变指令 - ng-class - ;你只需要更新选项对象。在控制器的某个地方,你可以这样做:

myDirectiveOptions.someClass = 'someOtherCustomClass';

由于Angular绑定的魔力,myDirective中的ng-class应该自动拾取它。此更改不必在myDirective的控制器内。

答案 2 :(得分:2)

您可以使用第二个指令来查找第一个指令的结果。只要确保&#34; mybluedirective&#34;优先于&#34; mydirective&#34;。

Js Fiddle:http://jsfiddle.net/XHJC2/

angular.module("demo", []).
    controller('SampleCtrl', function ($scope) {

    }).
    directive('mybluedirective', function () {
        return {
            priority: 4000,
            restrict: 'A',           
            link: function (scope, elem, attr) {
                elem.find('div').html('modified!');
            }
        };
    }).
    directive('mydirective', function() {
        return {
            priority: 40,
            restrict: 'A',           
            template:   '<div>TEST</div>'
        };
    });

以下是关于&#34;优先级&#34;在指令中:https://docs.angularjs.org/api/ng/service/$compile#-priority-