修改指令中的模板(动态添加另一个指令)

Modify template in directive (dynamically adding another directive)

本文关键字:指令 动态 添加 另一个 修改      更新时间:2023-09-26

问题

通过自定义指令动态添加ng-bind属性,以便能够在自定义指令中使用ng-bind、ng-bind-htmling-bind-html unsafe,而无需在任何位置手动添加到模板定义中。

示例

http://jsfiddle.net/nstuart/hUxp7/2/

断开的指令

angular.module('app').directive('bindTest', [
'$compile',
function ($compile) {
    return {
        restrict: 'A',
        scope: true,
        compile: function (tElem, tAttrs) {
            if (!tElem.attr('ng-bind')) {
                tElem.attr('ng-bind', 'content');
                $compile(tElem)
            }
            return function (scope, elem, attrs) {
                console.log('Linking...');
                scope.content = "Content!";
            };
        }
    };
}]);

解决方案

不知道。真的,我不明白为什么上面的小提琴不起作用。尝试了一下,去掉了额外的$compile

变通办法

我可以通过在指令中添加模板值来解决这个问题,但这会将内容封装在一个额外的div中,如果可能的话,我希望能够做到这一点。(见小提琴(

第二个变通办法

请在此处查看小提琴:http://jsfiddle.net/nstuart/hUxp7/4/(正如Ikarus博士在下文中所建议的(。我现在认为这是一种变通方法,因为在进入链接功能之前,你仍然可以修改模板,并且应该找到/应用更改。

您可以在链接函数内部进行编译,如下所示:

angular.module('app').directive('bindTest', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        scope: true,
        link: {
            post: function(scope, element, attrs){
                if (!element.attr('ng-bind')) {
                    element.attr('ng-bind', 'content');
                    var compiledElement = $compile(element)(scope);
                }
                console.log('Linking...');
                scope.content = "Content!";                
            }
        }
    };
}]);

让我知道这对你有多好http://jsfiddle.net/bPCFj/

这种方式看起来更优雅(不依赖$compile(,适合您的情况:

angular.module('app').directive('myCustomDirective', function () {
    return {
        restrict: 'A',
        scope: {},
        template: function(tElem, tAttrs) {
            return tAttrs['ng-bind'];
        },
        link: function (scope, elem) {
            scope.content = "Happy!";
        }
    };
});

jsFiddle:http://jsfiddle.net/hUxp7/8/

根据Angular指令文档:您可以将template指定为表示模板的字符串,也可以指定为接受两个参数tElement和tAttrs(在下面的编译函数api中描述(并返回表示模板的串值的函数

源代码告诉一切!检查compileNodes()函数及其对collectDirectives()的使用。

首先,collectDirectives查找单个节点上的所有指令。在我们收集了该节点上的所有指令后,然后将指令应用于该节点。

因此,当bindTest指令上的compile函数执行时,正在运行的$compile()已经过了收集要编译的指令的时间点。

bindTest指令中对$compile的额外调用将不起作用,因为您没有将该指令链接到$scope。您没有访问compile函数中的$scope的权限,但您可以在link函数中使用相同的策略,在该函数中您可以访问$scope

你们太亲密了。

function MyDirective($compile) {
    function compileMyDirective(tElement) {
        tElement.attr('ng-bind', 'someScopeProp');
        return postLinkMyDirective;
    }
    function postLinkMyDirective(iScope, iElement, iAttrs) {
        if (!('ngBind' in iAttrs)) {
            // Before $compile is run below, `ng-bind` is just a DOM attribute
            // and thus is not in iAttrs yet.
            $compile(iElement)(iScope);
        }
    }
    var defObj = {
        compile: compileMyDirective,
        scope: {
            someScopeProp: '=myDirective'
        }
    };
    return defObj;
}

结果将是:

<ANY my-directive="'hello'" ng-bind="someScopeProp">hello</ANY>