我正在尝试创建一个指令,允许将一个元素定义为可点击或不可点击,并且定义如下:
<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/