Angularjs Communication Between Directives

AngularJS communication between directives

One way you can communicate between them using what is called eventing.

One directive can emit an event on the rootscope which can then be listened by anybody who wants to. You could use $rootScope.$emit or $rootScope.$broadcast to publish events with data and use $scope.$on to listen to the event. In your case you could just do $scope.$emit as well.

app.directive("firstDir", function(){
return {
restrict : 'E',
controller : function($scope){
this.data = 'init value';

this.set = function(value){
//EMIT THE EVENT WITH DATA
$scope.$emit('FIRST_DIR_UPDATED', value);
this.data = value;
// communication with second Directive ???
}
},
controllerAs : 'firstCtrl'
};
});

app.directive("secondDir", function(){
return {
restrict : 'E',
controller : function($scope){
var _that = this;
//LISTEN TO THE EVENT
$scope.$on('FIRST_DIR_UPDATED', function(e, data){
_that.data = data;
});
this.data = 'init value';
},
controllerAs : 'secondCtrl'
};
});

Demo
Demo2

____________________________________________________________________________

Now speaking of which, it sometimes is really required to inject $rootScope just to have the eventing enabled to a different node in your application. You can instead have a pub/sub mechanism easily built in your app and make use of prototypical inheritance.

Here i am adding 2 methods publish and subscribe on $rootScope's prototype during app initialization. So any child scope or isolated scope will have these methods available and communication will be so easier without worrying about whether to use $emit, $broadcast, whether i need to inject a $rootscope for communication from isolated scoped directive etc.

app.service('PubSubService', function () {

return {Initialize:Initialize};

function Initialize (scope) {
//Keep a dictionary to store the events and its subscriptions
var publishEventMap = {};

//Register publish events
scope.constructor.prototype.publish = scope.constructor.prototype.publish
|| function () {
var _thisScope = this,
handlers,
args,
evnt;
//Get event and rest of the data
args = [].slice.call(arguments);
evnt = args.splice(0, 1);
//Loop though each handlerMap and invoke the handler
angular.forEach((publishEventMap[evnt] || []), function (handlerMap) {
handlerMap.handler.apply(_thisScope, args);
})
}

//Register Subscribe events
scope.constructor.prototype.subscribe = scope.constructor.prototype.subscribe
|| function (evnt, handler) {
var _thisScope = this,
handlers = (publishEventMap[evnt] = publishEventMap[evnt] || []);

//Just keep the scopeid for reference later for cleanup
handlers.push({ $id: _thisScope.$id, handler: handler });
//When scope is destroy remove the handlers that it has subscribed.
_thisScope.$on('$destroy', function () {
for(var i=0,l=handlers.length; i<l; i++){
if (handlers[i].$id === _thisScope.$id) {
handlers.splice(i, 1);
break;
}
}
});
}

}
}).run(function ($rootScope, PubSubService) {
PubSubService.Initialize($rootScope);
});

and you could just have any place from your app publish an event without requiring a rootScope.

$scope.publish('eventName', data);

and listen anywhere on the application without worrying about using $rootScope or $emit or $broadcast:-

$scope.subscribe('eventName', function(data){
//do somthing
});

Demo - PubSub

Communication between Controller and Directive in angularjs

Don't know if I got your problem but maybe this is a possible solution.

You can pass the issue as argument to your directive in this way:

app.directive("userIssues", function(){

return{

    restrict: 'E',
scope: { issue: '=' },
templateUrl: 'userissues.html'

}

});

and you can use it like this:

<user-issues ng-repeat="issue in issues" issue="issue"></user-issues>

Try this fiddle for an example

Hope this is what you need

AngularJS: Communication between directives

You can also do $rootScope.$broadcast events like playerStarted. This event can be subscribed by all directives and they can react to this event by stopping themselves. The one thing that you need to do would be pass in the data about the player which is starting so that the new player does not stop itself as it too would subscribe to such event.

AngularJS: Communication between directives and view updation

emit 'model:updated' inside scope.$apply in myItem directive since afterChange is a non-angular event

Communication between directives (and other parts) in AngularJS

require is particularly useful if you want to create custom form controls (see section Implementing custom from controls) -- i.e., you want to create your own form control with a directive. You can require the ngModelController to get access a lot of existing functionality via its API/functions.

Another use case is found on the AngularJS home page, section Create Components, where the pane directive uses require: '^tabs' to get access to the tabs controller. Since both of these components/directives create isolate scopes, scope inheritance is not an option. A service wouldn't be a good fit either, since your app could have multiple tabs directives. So, in this case, the controller is used as a means for the pane directive to be able to affect the tabs scope -- to be able to get at the scope. Without using require, the pane directive can't get at the tabs scope. I discuss this in more detail (with a picture) in this SO answer: 'this' vs $scope in AngularJS controllers

require can only be used if the controller-of-interest is defined on the same element (e.g., ngModelController), or if there is a hierarchy (e.g., pane -> tab).

Communication between unrelated directives

There is a lot of potential pitfalls when using events. For this particular case I would propose to use a service (you can bundle it with banner directive into the banner submodule).

Your directive can then register the listener to trigger banner update. Then call some updateBannerData(data) of this service which will call the listener to trigger banner change. Here is some code directly from my head (hopefully without errors...)

.factory('bannerService', function() {
var bannerService = {
listener: null,
onUpdate(listener) {
bannerService.listener = listener;
}
updateBannerData: function(data) {
if(listener) {
listener(data);
}
}
};
return bannerService;
})
// inject bannerService here:
.directive('appBanner', [function (bannerService) {
return {
restrict: 'E',
replace: true,
controller: function ($scope) {
bannerService.onUpdate(function (data) {
// code to fetch banner from db here
});
}
};
}]);


Related Topics



Leave a reply



Submit