1

I need somehow to emit event from part of the page (scrolling, clicking) that is served by one directive to other parts of the page, served by other controller so that it could be updated accordingly. Use case - for example Word document with annotations that are moving along with the page in the viewport. SO in my design I have directive with link method in it and I need to broadcast events from it to other controllers in my app. What I have inside my link function:

 element.bind('click', function (e) { 
    var eventObj = element.scrollTop();
    scope.$broadcast('app.scrollOnDocument', eventObj);
 });

This event cannot I cannot be see in other controllers directly - so code like this in other controller doesn't work:

$scope.$on('app.scrollOnDocument', function (e, params) {
   console.log(e, params);
});

So what I have to do is to intercept those events in the same directive's controller and broadcast them to the higher scope like:

$scope.$on('app.scrollOnDocument', function(event, params){
     //go further only if some_condition
      if( some_condition ){
         $rootScope.$broadcast('app.scrollOnDocumentOuter', params);
      }
});

I am not sure this is the correct way of doing this. Maybe I am missing some directive property or setting to make it possible?

2 Answers 2

7

Non standard services can be passed to a directive like

.directive('notify', ['$rootScope', '$interval', function(rootScope, interval){

    return {
      restrict : 'E',
      link : function(){
          interval(function(){
            rootScope.$broadcast('custom.event', new Date());
          }, 1500);

        }
      };
}]);

The example below broadcasts an event every 1500ms.

If using the rootScope for communication cannot be avoided,you should always try unregistering the listener.

angular.module('app', [])
  .controller('indexCtrl', ['$rootScope', '$scope',
    function(rootScope, scope) {
      scope.title = 'hello';
      scope.captured = [];

      var unregister = rootScope.$on('custom.event', function(evt, data) {
        scope.captured.push(data);
      });

      scope.$on('$destroy', function() {
        unregister();
      });

    }
  ])
  .directive('notify', ['$rootScope', '$interval',
    function(rootScope, interval) {

      return {
        restrict: 'E',
        link: function() {
          interval(function() {
            rootScope.$broadcast('custom.event', new Date());
          }, 1500);

        }
      };
    }
  ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app" ng-controller="indexCtrl">
  <h1>{{title}}</h1>
  <notify></notify>
  <ul>
    <li ng-repeat="event in captured">{{event|date:'medium'}}</li>
  </ul>
</div>

Sign up to request clarification or add additional context in comments.

Comments

0

For broadcasting in AngularJS, you always have to use $rootScope. You are listening always on $scope instead of $rootScope.

1 Comment

I know that $rootScope should be used for global app events. But there was no $rootScope available in directive link function if I am correct. I am sure I've tried that, anyway I'll check and be back with updates within couple of days.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.