Reputation: 9993
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?
Upvotes: 1
Views: 6624
Reputation: 12368
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>
Upvotes: 7
Reputation: 3831
For broadcasting in AngularJS, you always have to use $rootScope
. You are listening always on $scope
instead of $rootScope
.
Upvotes: 0