javascript - 在指令链接功能中动态添加 ng-click

标签 javascript angularjs angularjs-directive

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

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

我希望生成的 HTML 是:

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

我的指令实现如下所示:

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,但它会导致无限链接/编译循环。

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

最佳答案

更好的解决方案(新):

看完Angular docs之后我遇到了这个:

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.

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

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

注意新的模板函数。现在,我在编译之前在该函数内部操作模板。

替代解决方案(旧):

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

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

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

虽然我认为第二次重新编译模板并不理想,所以我觉得在第一次编译模板之前仍然有办法做到这一点。

关于javascript - 在指令链接功能中动态添加 ng-click,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22116470/

相关文章:

javascript - Ajax 循环调用

javascript - 如何在 ag-grid cellEditor 组件内渲染 Angular Directive(指令)?

angularjs - 无限滚动不启用滚动首先导致 Angular js

javascript - karma 指令 templateUrl

javascript - 在 Stimulus Controller 中使用 querySelector 检索动态元素时出现问题

javascript - 静态大小的外部元素,尤其是在右侧和下方使用 .animate()

javascript将html输入类型id传递给函数

AngularJS 过滤器触发无限 $digest 循环

angularjs-directive - typescript 错误 TS2339 : Property 'project' does not exist on type '{}'

angularjs - 如何使用 Twitter typehead.js 和 Angular 编译功能?