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.
如果我在sample指令上将replace属性设置为false,则它可以正常工作。我想这是因为在事件被触发的时刻,元素样本不再存在,因此它将被内部模板替换。
So, how do I accomplish this?
那么,我该如何做到这一点?
Doing this, as suggested in the answer below, will not accomplish my purpose:
如下面的答案所示,这样做不会达到我的目的:
$($element).trigger("myEvent.sample", [something]);
2 个解决方案
#1
16
Please find below the fiddle
请在下面找到小提琴
小提琴
Trigger is a jquery function which will work on proper handler.
触发器是一个jquery函数,它将适用于正确的处理程序。
$(element).trigger("myEvent.sample");
Hope this helps
希望这可以帮助
#2
4
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.由于角度转换DOM的方式,我建议在主体上附加所有自定义侦听器,然后按事件目标过滤它们。 $('body')。on('myEvent.sample','target-selector-expr',handler)就是这么做的。例如,如果在ngRepeated元素上使用自定义事件侦听器,则不会执行处理程序,因为在尝试将事件附加到它们时这些元素不存在。
-
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的jqLite实现在触发事件时有些缺乏功能。因此我在jQuery($($ element))中包装了sample的元素,否则额外的数据将无法到达处理程序。
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);
});
});
#1
16
Please find below the fiddle
请在下面找到小提琴
小提琴
Trigger is a jquery function which will work on proper handler.
触发器是一个jquery函数,它将适用于正确的处理程序。
$(element).trigger("myEvent.sample");
Hope this helps
希望这可以帮助
#2
4
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.由于角度转换DOM的方式,我建议在主体上附加所有自定义侦听器,然后按事件目标过滤它们。 $('body')。on('myEvent.sample','target-selector-expr',handler)就是这么做的。例如,如果在ngRepeated元素上使用自定义事件侦听器,则不会执行处理程序,因为在尝试将事件附加到它们时这些元素不存在。
-
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的jqLite实现在触发事件时有些缺乏功能。因此我在jQuery($($ element))中包装了sample的元素,否则额外的数据将无法到达处理程序。
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);
});
});