Bind events to AngularJS element directives using jQuery

I have a directive in 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 this way:

 <sample id="myElement"> <item>1</item> <item>2</item> </sample> 

What will be displayed 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:

 $("#myElement").on("myEvent.sample", function (e, something) { alert("click: " + something); }); 

I want this event to fire whenever the link is clicked.

If I set the replace property to false in the sample directive, it works. I assume this is because the moment the event is fired, the sample element no longer exists, and as such it will be replaced by an internal template.

So how to do this?

Doing this as suggested in the answer below will not achieve my goal:

 $($element).trigger("myEvent.sample", [something]); 
+7
jquery angularjs javascript-events events angularjs-directive
source share
2 answers

Below is the script

fiddle

Trigger is a jquery function that will work with the corresponding handler.

 $(element).trigger("myEvent.sample"); 

Hope this helps

+16
source share

Here's the updated fiddle: http://jsfiddle.net/3u3zh/1/

A few points should be noted:

  • Due to the way angular converts the DOM, I would advise attaching all your custom listeners to the body and then filtering them by purpose. $('body').on('myEvent.sample', 'target-selector-expr', handler) does just that. For example, if you use custom event listeners in ngRepeat ed elements, your handlers will not be executed because these elements will not exist while trying to attach events to them.

  • It seems that the implementation of angular jqLite is somewhat absent in functions when events are fired. So I wrapped the sample element in jQuery ( $($element) ), because otherwise the extra data will not get into the handler.

Final template:

 <div ng-app="myApp"> <sample id="myElement"><item>1</item><item>2</item></sample> </div> 

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); }); }); 
+4
source share

All Articles