在指令链接功能中动态添加 ng-click [英] Add ng-click dynamically in directive link function

查看:29
本文介绍了在指令链接功能中动态添加 ng-click的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个指令,允许将元素定义为可点击或不可点击,并且定义如下:

I'm trying to create a directive that would allow an element to be defined as clickable or not, and would be defined like this:

<page is-clickable="true">
    transcluded elements...
</page>

我希望生成的 HTML 是:

I want the resulting HTML to be:

<page is-clickable="true" ng-click="onHandleClick()">
    transcluded elements...
</page>

我的指令实现如下所示:

My directive implementation looks like this:

app.directive('page', function() {
    return {
        restrict: 'E',
        template: '<div ng-transclude></div>',
        transclude: true,
        link: function(scope, element, attrs) {
            var isClickable = angular.isDefined(attrs.isClickable) && scope.$eval(attrs.isClickable) === true ? true : false;

            if (isClickable) {
                attrs.$set('ngClick', 'onHandleClick()');
            }

            scope.onHandleClick = function() {
                console.log('onHandleClick');
            };
        }
    };
});

我可以看到在添加新属性后,Angular 不知道 ng-click,所以它不会触发.我尝试在设置属性后添加 $compile ,但它会导致无限链接/编译循环.

I can see that after adding the new attribute, Angular does not know about the ng-click, so it is not firing. I tried adding a $compile after the attribute is set, but it causes an infinite link/compile loop.

我知道我可以在 onHandleClick() 函数内部检查 isClickable 值是否为 true,但我很好奇如何将通过动态添加 ng-click 事件来执行此操作,因为我可能需要使用多个其他 ng-* 指令来执行此操作,而我不想添加不必要的开销.有什么想法吗?

I know I can just check inside the onHandleClick() function if the isClickable value is true, but I'm curious how one would go about doing this with dynamically adding an ng-click event because I may need to do with this with multiple other ng-* directives and I don't want to add unnecessary overhead. Any ideas?

推荐答案

更好的解决方案(新):

在阅读Angular 文档后,我发现了这个:><块引用>

您可以将模板指定为表示模板的字符串或作为带有两个参数 tElement 和 tAttrs 的函数(在下面的编译函数 api) 并返回一个字符串值表示模板.

Better Solution (New):

After reading through the Angular docs I came across this:

所以我的新指令看起来像这样:(我相信这是处理这类事情的合适的Angular"方式)

You can specify template as a string representing the template or as a function which takes two arguments tElement and tAttrs (described in the compile function api below) and returns a string value representing the template.

So my new directive looks like this: (I believe this is the appropriate "Angular" way to go about this type of thing)
</div>';},转置:真实,链接:函数(范围,元素,属性){scope.onHandleClick = function() {console.log('onHandleClick');};}};});

app.directive('page', function() { return { restrict: 'E', replace: true, template: function(tElement, tAttrs) { var isClickable = angular.isDefined(tAttrs.isClickable) && eval(tAttrs.isClickable) === true ? true : false; var clickAttr = isClickable ? 'ng-click="onHandleClick()"' : ''; return '<div ' + clickAttr + ' ng-transclude></div>'; }, transclude: true, link: function(scope, element, attrs) { scope.onHandleClick = function() { console.log('onHandleClick'); }; } }; });

注意新的模板函数.现在我在编译之前操作该函数中的模板.

Notice the new template function. Now I am manipulating the template inside that function before it is compiled.

添加了 replace: true 以消除重新编译指令时的无限循环问题.然后在链接函数中,我只是在添加新属性后重新编译元素.不过要注意一件事,因为我的元素上有一个 ng-transclude 指令,所以我需要删除它,这样它就不会在第二次编译时尝试嵌入任何内容,因为没有什么可以嵌入的.

Added replace: true to get rid of the infinite loop issue when recompiling the directive. And then in the link function I just recompile the element after adding the new attribute. One thing to note though, because I had an ng-transclude directive on my element, I needed to remove that so it doesn't try to transclude anything on the second compile, because there is nothing to transclude.

这就是我的指令现在的样子:

This is what my directive looks like now:

app.directive('page', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<div ng-transclude></div>',
        transclude: true,
        link: function(scope, element, attrs) {
            var isClickable = angular.isDefined(attrs.isClickable) && scope.$eval(attrs.isClickable) === true ? true : false;

            if (isClickable) {
                attrs.$set('ngClick', 'onHandleClick()');
                element.removeAttr('ng-transclude');
                $compile(element)(scope);
            }

            scope.onHandleClick = function() {
                console.log('onHandleClick');
            };
        }
    };
});

不过我觉得第二次重新编译模板并不理想,所以我觉得在第一次编译模板之前还是有办法做到这一点的.

I don't think that recompiling the template a second time is ideal though, so I feel that there is still a way to do this before the template is compiled the first time.

这篇关于在指令链接功能中动态添加 ng-click的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆