0

I know if I have two directives that are nesting I can communicate throw controller, require and pass it as the fourth parameter of the link function.

<my-first-div>
   <my-seconded-div></my-seconded-div>
</my-first-div>

and every thing will work fine. but I could do the same thing when they weren't nesting.

<my-first-div></my-first-div>
<my-seconded-div></my-seconded-div>

why ? and how do I make them communicate ?

user24136
  • 135
  • 4
  • 13

2 Answers2

2

It happens since both of the directives have watchers on the same variable reference. So the changed value is being 'noticed' in all the relevant directives.

You could mimic this "communication" by passing the same variable (By Reference) (varName:'=') for both directives and place watchers on that variable inside each of these directives.

Then, the DOM hierarchy won't matter

For example: Directive 1:

app.directive('directive1', function () {
  return {
    restrict: 'E',
    scope: {
      myVar: '='
    }
    link: function (scope, element, attrs) {
        // do something with main directive
        console.log("directive1", scope.myVar);

        $scope.$watch("scope.myVar", function (value) {
            console.log("directive1", "value changed to:" + scope.myVar)
        });
    }
   }
});

The same for the second directive.. For both directives pass the same variable And the magic will happen

Alon Kogan
  • 3,258
  • 1
  • 21
  • 20
1

I assume by saying communicating, you mean sharing data, state and events between two directives. I will list basic ways that I have in mind here:

  1. The reason why you can pass data/state between two nested directives is because in AngularJS a child directive (nested one in your example) inherits the scope of it parents. As the results, two sibling directives can share same data from its parent controller.

<div ng-controller="ParentCtrl">
  <ng-sibling></ng-sibling>
  <ng-another-sibling></ng-another-sibling>
</div> 

In the above piece of code, ng-sibling and ng-another-sibling will inherit the same data that is defined in their parent ParentCtrl

  1. AngularJS support emitting/broadcasting event/data using $broadcast, $emit and $on function, document can be found here: https://docs.angularjs.org/api/ng/type/$rootScope.Scope.

    $emit can be used to sent event upward the tree's hierarchy, while $broadcast's downward, and the direction is essential.

    So one of your directive can dispatch the event, while the other listen to it. It's pretty similar to the way jQuery trigger events.

// In link function or controller of one directive
$scope.$broadcast("EVENT_A",my_data);

// Listen to EVENT_A on another directive
$scope.$on("EVENT_A",function($event,data){
  ....
})
  1. While two-way binding or firing event arbitrarily can be useful at first, they can also lead to the situation when it's really difficult to keep track of the application's event and data flow. If you find this situation, maybe consider using Flux architecture with AngularJS not a bad idea. Redux fully supports AngularJS and all of your directives can be built as single-state components. The Github repo can be found here: https://github.com/angular-redux/ng-redux, and a simple tutorial on how to run AngularJS with Redux can be found here: http://blog.grossman.io/angular-1-using-redux-architecture/
Thai Duong Tran
  • 2,453
  • 12
  • 15
  • with $emit and $broadcast wouldn't I expose my self to much or the data ? – user24136 Feb 02 '17 at 11:45
  • And another thing I didn't mention, I wanted to do it ( not for a any reason but to learn ) without any controller, so your first answer is good but I tried to avoid it. I did find out it can be done by angular.element(element), this give me direct approach to the detective element that I wanted and access to its scope as well. – user24136 Feb 02 '17 at 11:51
  • Yes, and ussually, a directive/component should only be exposed to the specific data that it needs. It doesn't mean I say using it over sharing scope/reference. Scope reference should be the main way to pass data between directives of your application. At the same time, broadcasting should be used to control data updates / changes in your application, for example you can use $broadcast to signify other component what to do after a button is clicked. – Thai Duong Tran Feb 02 '17 at 12:21
  • Regarding your second comment, basically you dont need to declare a controller if you dont want to. Any directives in AngularJs itself are controlled by controllers. Three main parts of an AngularJS directive are the view, the controller and the observer. I suggest you study Angularjs document about directive to have a better understanding about it. – Thai Duong Tran Feb 04 '17 at 09:21