Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS communication between directives

I'am new to Angular.js, I need for my application some communication between directives, I read some documentation about link and require, but can't understand exactly how it works.

For a simple example I have : live fiddle : http://jsfiddle.net/yw235n98/5/

  • 2 directives : firstDir, secondDir :: with some data
  • firstDir have a click function that will change the data value
  • when firsDir click function is triggered I want to change data in secondDir too.

HTML :

<body ng-app="myApp"> First Directive :    <first-dir >     <h3>{{firstCtrl.data}}</h3>     <button ng-click="firstCtrl.set('NEW VALUE')">Change Value</button> </first-dir> Second Directive :  <second-dir>     <h3>{{secondCtrl.data}}</h3> </second-dir> 

Javascript :

(function(){     var app = angular.module('myApp', []);      app.directive("firstDir", function(){         return {             restrict : 'E',             controller : function(){                         this.data = 'init value';                 this.set = function(value){                     this.data = value;                     // communication with second Directive ???                 }                    },             controllerAs : 'firstCtrl'         };       });      app.directive("secondDir", function(){         return {             restrict : 'E',             controller : function(){                         this.data = 'init value';                },             controllerAs : 'secondCtrl'         };       }); })(); 
like image 764
tibbus Avatar asked Aug 12 '14 21:08

tibbus


People also ask

How do I pass data from one directive to another directive in AngularJS?

The best way to pass an object to an angular directive is by using the &. When you use &, angular compiles the string as an expression and sets the scope variable in your directive to a function that, when called, will evaluate the expression in the context of the directive's parent's scope.

What is $parent in AngularJS?

$scope.$parent refers to the $scope of the parent element.

Can we use multiple directives in AngularJS?

... is quite illustrative as AngularJS doesn't allow multiple directives (on the same DOM level) to create their own isolate scopes. According to the documentation, this restriction is imposed in order to prevent collision or unsupported configuration of the $scope objects.

How does directive work in AngularJS?

AngularJS directives are extended HTML attributes with the prefix ng- . The ng-app directive initializes an AngularJS application. The ng-init directive initializes application data. The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.


1 Answers

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

like image 110
PSL Avatar answered Oct 22 '22 15:10

PSL