Search code examples
javascriptangularjsangularjs-directiveangularjs-scopedom-events

Change in $document.on('click') not reflected in view


I have an angular directive ngx-notifications, it sits inside a controller MenuBarController.

View

<div class="row" ng-controller="MenuBarController">
 ...
  <span ng-click="ShowNotifications()">click me</span>
  <div ng-show="NotificationsVisible" ngx-notifications="NotificationsVisible">

Controller

$scope.NotificationsVisible = false;

function ShowNotifications(){
  $scope.NotificationsVisible = !$scope.NotificationsVisible;
}


setInterval(function(){
  console.log($scope.NotificationsVisible);
},1000);

Directive

angular.module('app').directive('ngxNotifications', NotificationsDirective);

NotificationsDirective.$inject = ['$document'];
function NotificationsDirective($document) {

  return {
    restrict: "A",
    scope: false,
    link: function ($scope, $elem, $attr) {
      var key = $attr.ngxNotifications;

      $document.on("click",function ($e) {
        if(!$elem[0].contains($e.target)){
          console.log($scope,key); // logs correct scope and key
          //neither of the two following lines are reflected in the view
          $scope[key] = false;
          $scope.NotificationsVisible = false;

        }
      });

    }
  }
}

The span[ng-click] toggles the visibility of my notification box, but for some reason when my directive changes it via $document.on('click') angular doesn't pick up the change, despite the fact that my setTimeout in the controller shows that the value HAS changed. Why is this?

I can't create a separate scope between my controller and my directive, I just need to add this extra functionality.


Solution

  • As I suspected, for some reason the $document::on method is not part of the angular digest, adding $scope.$apply worked, but this doesn't really make sense (I never left angular code to change the model):

    $document.bind("click",function ($e) {
      if($scope[key] && !$elem[0].contains($e.target)){
        $scope.$apply(function () {
          $scope[key] = false;
        });
      }
    });