Dyego Oviedo
Dyego Oviedo

Reputation: 308

Jquery click event inside Angular controller issue: loop many times

I am developing an app with onsen UI (angular based) + phonegap. So I have a JQuery click event inside an angular controller and it is the problem.

When I back page stack and go again, It triggers the click event many times.

I am using jquery click event inside angular controller because I must use a Onsen UI Service inside this event. So I must declare this event inside the controller. But this is the problem. Look:

module.controller('ListController', function($scope, EventsService, OneEventService) {

  $scope.events = EventsService.getPopular();

  //this is the event that is triggering many times
  $(document).on("click",".item-from-list",function(e){...}

I tried to use $(element).click(func) but It cannot get the DOM element. Then I use $(document).on("click", elem, func)

So how can I fix this?

Upvotes: 2

Views: 4333

Answers (1)

Arkantos
Arkantos

Reputation: 6608

This is because you're registering your click handler on document everytime your controller is initialized. Each time you navigate to some other page/view and come back to the same page again, the controller is initialized (i.e all the code in your controller is executed), so jQuery is adding a new click event listener every time on the document.

You can resolve this in 2 ways.

Option-1:

Using jQuery's off() to de-register the existing click handlers before adding a new one.

 `$(document).off().on("click",".item-from-list",eventHandlerFn);`

Option-2:

Using Angular's scope based event handlers like ng-click which are de-registered automatically when controller goes out of scope i.e when you move to new page.

<div class='item-from-list' ng-click='handleClick()'></div>

 module.controller('ListController', function($scope) {

      $scope.handleClick= function(){ /*  handle click event here */ };

 }

One of the fundamental philosophies of AngularJS is to keep DOM manipulation out of the Controllers, so I suggest the second way to resolve your issue. There's even a third way with custom directives where-in you get a reference to your element and you can register your click handler using jQuery or using the default jQLite's on().

module.directive('registerClick',function(){

  return {
        restrict : 'A',
        link: function (scope, element, attrs) {

            /* register your event handler here */
            element.on('click', clickHandlerFn);

            /* As we're explicitly registering the handler, we need 
              to de-register it, once your element is destroyed like below */

            element.on('$destroy', function () {
                element.off('click', clickHandlerFn);
            });
        }
    };

});

Upvotes: 8

Related Questions