I have a controller "MyController" and a directive "MyDirective" in separate modules "app" and "directiveModule" respectively. DirectiveModule has been injected into the angular.module of "app".
The issue I am having is as part of "app", I have a controller that emits an event "TEST" that the controller for the directive does not pick up. How can I successfully get the directive of its own module to catch the emit? Is this possible? (Note: I tried $scope originally, then used $rootScope, but both do not make a difference.)
My controller:
app.controller('MyController', function($scope, $rootScope) {
$rootScope.$emit('TEST');
});
My directive:
directiveModule.directive('MyDirective', ['$rootScope', 'MyService',
function($rootScope, MyService) {
return {
restrict: 'E',
controller: ['$scope', '$rootScope', function($scope, $rootScope) {
$rootScope.$on('TEST', function() {alert("Event Caught")})
}]};
}];
UPDATE: It looks like my directive has not initiated by the time the event is broadcast. Is there a way to make it such that I could "wait for directive to instantiate" as opposed to waiting an arbitary "1000" ms or another alternative?
I think the only case your directive needs to catch that event is to get some initial data depending on the MyController
because if your directive is independent of the MyController
, you don't need to catch that event, just initiate the directive independently.
My solution is using $watch to get notified when the initial data from the MyController
is ready.
app.controller('MyController', function($scope) {
$scope.data = {}; //initialize the data, this data could be fetched from an ajax
});
directiveModule.directive('MyDirective', ['MyService',
function(MyService) {
return {
restrict: 'E',
controller: ['$scope', function($scope) {
$scope.$watch("data",function(newValue,OldValue,scope){
//do your work here when data is changed.
});
}]};
}];
In case you use isolate scope in your directive:
directiveModule.directive('MyDirective', ['MyService',
function(MyService) {
return {
restrict: 'E',
scope : {
directiveData:"=",
},
controller: ['$scope', function($scope) {
$scope.$watch("directiveData",function(newValue,OldValue,scope){//watch on the directive scope property
//do your work here when data is changed.
});
}]};
}];
Your html may look like this:
<my-directive directive-data="data" /> //bind isolate scope directive property with controller's scope property.
I think below questions are some similar cases like this:
all modules injected into main module share same rootScope. $emit
however travels up the scope tree, you need $broadcast
.
If you $broadcast
from $rootScope
it will be received by all active scopes so in directive could actually use $scope.$on
and wouldn't need to inject $rootScope
just for the purpose of using $on
Similarly if directive is descendant of the controller, could also broadcast from controller scope
You can. Demo: http://plnkr.co/edit/vrZgnu?p=preview
A side note: if you try to communicate to children element that is lower in DOM tree, you should use $broadcast
. $emit
is used to communicate with parents elements ("up" direction).
But your true problem might be that when you tried to emit the event, the directive might not be initiated yet. I used $timeout
service to wait 1000ms to broadcast the event.
If you don't want to wait a arbitrary 1000ms, you can let your directive $emit
"ready" event to inform controller that it's ready. Then broadcast from the controller.
Also removed the 1000ms in this demo http://plnkr.co/edit/GwrdIw?p=preview, everything still works. But I don't think this is a reliable solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With