Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing communication between independent AngularJS directives independently

Tags:

angularjs

This is more of an organizational approach to solving this issue rather than a direct solution. My question itself is that if I have two directives which are not dependent on each other and can both work independently to serve their purposes. But if one of the directives is present then the other one needs to execute once the other is ready. In this case then what would be the logical way to make sure that it works out that way without the need to hardcode any function calls or events?

Lets say for example you have one directive which builds a grid of some sort:

angular.module('App').directive('appGrid',function() {
  return function($scope, element) {
    $scope.rows = ...
  };
});

Then I have another directive that makes the element horizontally scrollable:

angular.module('App').directive('appPane',function() {
  return function($scope, element) {
    element.attachHorizontalScroll();
  };
});

So an example of my HTML would look like this:

<div data-app-grid data-app-pane>
  <div data-ng-repeat="row in rows">
    <div data-ng-repeat="cell in row.cells">
      {{ cell.data }}
    </div>
  </div>
</div>

Basically the appPane directive needs to run after the appGrid directive has been executed and the table is ready.

One solution I can think of is to watch the data to see when it is ready using the $scope.$watch method, but this poses a problem since the change can occur multiple times and this would be bad design to redundantly update the page and it also poses a problem if multiple directives are writing to the same scope variable that is being watched.

Another solution is to have the first directive emit an event (something like elementReady) and then have the 2nd directive take over. But what about if the first directive isn't there? Then how would the 2nd directive know when to do it's job? There could be another directive which is basically an empty directive which just fires the event for all other elements, but this is a bit of hack. Also what happens if multiple other directives fire the elementReady event?

One more solution is to create a 3rd directive which shares the logic between the two directives via a shared service. But this makes the 3rd directive fully reliant on both other directives as well as the shared services in between. This also require more, unnecessary testing code as well as actual code to write the directive (much more code compared to the 2nd solution, which would require only one + one lines of code).

Any ideas?

like image 796
matsko Avatar asked Nov 30 '12 05:11

matsko


People also ask

What is the difference between AngularJS directives and controllers?

A controller is usually used to contain and maintain the logic for your view, which gets bound to your view via $scope. A directive is something that you might use repeatedly and is called in your view directly through the directive name which you can pass in as an attribute.

Who controls the data flow in AngularJS?

AngularJS application mainly relies on controllers to control the flow of data in the application. A controller is defined using ng-controller directive. A controller is a JavaScript object that contains attributes/properties, and functions.

What is Attrs in AngularJS?

scope is an AngularJS scope object. element is the jqLite-wrapped element that this directive matches. attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values. controller is the directive's required controller instance(s) or its own controller (if any).

What are the binding directives in AngularJS?

The ng-bind directive tells AngularJS to replace the content of an HTML element with the value of a given variable, or expression. If the value of the given variable, or expression, changes, the content of the specified HTML element will be changed as well.


2 Answers

Have a look at the priority attribute of the directives.

Here is a copy of the exact description from the angular docs :

priority - When there are multiple directives defined on a single DOM element, sometimes it is necessary to specify the order in which the directives are applied. The priority is used to sort the directives before their compile functions get called. Higher priority goes first. The order of directives within the same priority is undefined.

you should be able to find it in

http://docs.angularjs.org/guide/directive

under the Writing directives (long version) --- Directives definition Object section.

Hope this answers your question.

like image 173
ganaraj Avatar answered Oct 05 '22 02:10

ganaraj


I had a similar problem. I couldn't use priority, since the wiring occurred after clicking on the element. I solved it using $rootScope. Here is a simplified example:

link : function (scope, element, attrs) {
   element.on('click', function() {
       $rootScope.$emit('myEvent', myData);
   });
}

In the other directive you 'listen' for myEvent:

link : function (scope, element, attrs) {
   $rootScope.$on('myEvent', function(data) {
      // do sth
   });
}
like image 32
asgoth Avatar answered Oct 05 '22 02:10

asgoth