AngularJS proper events biding with parent and child directives

1.3k Views Asked by At

I'm trying to implement popup window and button which reveals it. I'm doing that by the means of directives:

<div class="wrapper" wrapper>
  <div class="popup" ng-class="{'popup__active':isActive}">
    Popup message
  </div>
  <button btn>Click me</button>
</div>

When popup is visible I need to be able to close it by clicking anywhere outside of the popup.

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {

});

app.directive('wrapper', function($rootScope, $timeout) {
  return {
    link: function($scope, $element) {
      $rootScope.$on('btnclick', function() {
        $scope.isActive = true;
        $scope.$digest();
        $element.bind('click', function() {
          $scope.isActive = false;
          $element.unbind('click');
          $scope.$digest();
        });

      });
    },
  }
});

app.directive('btn', function($rootScope) {
  return {
    link: function($scope, $element) {
      $element.bind('click', function() {
        $rootScope.$broadcast('btnclick');
      });
    },
  }
});

There is a problem with this code. When I click the button it shows the popup and immediately hides it as the 'click' event is fired inside the wrapper link function. But that click event should be triggered only after popup is shown and I click anywhere outside of it.

See plunk: http://plnkr.co/edit/wRbbB7rdgLSaQDZQQEc1

Note: Unfortunately, the layout cannot be changed in real project due to complex CSS dependences. So I'm looking how to proper bind the elements using angular.

1

There are 1 best solutions below

0
On BEST ANSWER

As per your current structure you parent element and child element both has click event. When you clicked on any of the inner element it call the click event of that element and then it bubble ups the event as parent has the same event. To prevent this behavior you have to use event.stopPropagation() which will prevent the bubble up (send event to its parent element) on click event.

Directive

app.directive('btn', function($rootScope) {
  return {
    link: function($scope, $element) {
      $element.bind('click', function(e) {
        e.stopPropagation(); //stop bubbling up of event
        $rootScope.$broadcast('btnclick');
      });
    },
  }
});

Demo Plunkr