使用 jQuery 在 AngularJS 元素指令上绑定事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21929226/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bind events on AngularJS element directives using jQuery
提问by Milad Naseri
I have a directive in AngularJS:
我在 AngularJS 中有一个指令:
module = angular.module("demoApp", [], null);
module.directive('sample', function () {
return {
restrict: "E",
transclude: true,
replace: true,
template: "<div ng-transclude></div>",
controller: function ($scope, $element) {
this.act = function (something) {
//problematic line HERE
$element.trigger("myEvent.sample", [something]);
};
}
};
})
.directive('item', function () {
return {
restrict: "E",
require: "^sample",
transclude: true,
replace: true,
template: "<a ng-transclude style='display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;'></a>",
link: function (scope, element, attributes, parentController) {
element.on("click", function () {
parentController.act(this.innerText);
});
}
}
});
And in my HTML I use it thus:
在我的 HTML 中,我这样使用它:
<sample id="myElement">
<item>1</item>
<item>2</item>
</sample>
Which will be rendered as:
这将呈现为:
<div ng-transclude="" id="myElement">
<a ng-transclude="" style="display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;;display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;" class="ng-scope"><span class="ng-scope">1</span></a>
<a ng-transclude="" style="display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;;display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;" class="ng-scope"><span class="ng-scope">2</span></a>
</div>
I want to be able to listen to events triggered manually through jQuery:
我希望能够监听通过 jQuery 手动触发的事件:
$("#myElement").on("myEvent.sample", function (e, something) {
alert("click: " + something);
});
I want this event to be triggered whenever the link is clicked.
我希望每当单击链接时触发此事件。
If I set the replace
property to false
on the sample
directive, it works. I guess it is because at the point where the event is fired, the element sample
no longer exists, and as such it will have been replaced by the inner template.
如果我的设置replace
属性false
的sample
指令,它的工作原理。我想这是因为在触发事件时,元素sample
不再存在,因此它将被内部模板替换。
So, how do I accomplish this?
那么,我该如何实现呢?
Doing this, as suggested in the answer below, will not accomplish my purpose:
正如下面的答案所建议的那样,这样做不会达到我的目的:
$($element).trigger("myEvent.sample", [something]);
回答by Sai
回答by package
Here's updated fiddle: http://jsfiddle.net/3u3zh/1/
这是更新的小提琴:http: //jsfiddle.net/3u3zh/1/
There are several points worth noticing:
有几点值得注意:
Because of the way angular transforms DOM, I would advice attaching all your custom listeners on body and then filter them by event target.
$('body').on('myEvent.sample', 'target-selector-expr', handler)
does exactly that. For example, if you use custom event listeners onngRepeat
ed elements, your handlers would not be executed because those elements would not exist at the time of trying to attach events to them.It seems that angular's jqLite implementation is somewhat lacking in features when triggering events. Therefore I wrapped
sample
's element in jQuery ($($element)
) because otherwise the additional data would not get to the handler.
由于 angular 转换 DOM 的方式,我建议将所有自定义侦听器附加到 body 上,然后按事件目标过滤它们。
$('body').on('myEvent.sample', 'target-selector-expr', handler)
正是这样做的。例如,如果您在ngRepeat
ed 元素上使用自定义事件侦听器,则不会执行您的处理程序,因为在尝试将事件附加到它们时这些元素不存在。看来angular 的jqLite 实现在触发事件的时候有点缺乏功能。因此,我将
sample
的元素包装在 jQuery($($element)
) 中,否则附加数据将无法到达处理程序。
Final template:
最终模板:
<div ng-app="myApp">
<sample id="myElement"><item>1</item><item>2</item></sample>
</div>
Js:
JS:
var myApp=angular.module('myApp',[]);
myApp.directive('sample', function () {
return {
restrict: "E",
replace: true,
transclude: true,
template: "<div ng-transclude></div>",
controller: function ($scope, $element) {
this.act = function (something) {
$($element).trigger("myEvent.sample", [something]);
};
}
};
})
.directive('item', function () {
return {
restrict: "E",
require: "^sample",
transclude: true,
template: "<a ng-transclude></a>",
link: function (scope, element, attributes, parentController) {
element.on("click", function(e) {
parentController.act(this.innerHTML);
});
}
}
})
$(document).ready(function(){
$("body").on("myEvent.sample", '#myElement', function (e, something) {
alert('clicked: ' + something);
});
});