Directive to Directive Communication

The initial setup:

<body ng-app="greetings">
  <welcome>Say something!</welcome>
</body>
angular.module('greetings', [])
.directive("welcome", function() {
  return {
    restrict: "E",
    controller: function($scope) {
      $scope.words = [];

      this.sayHello = function() {
        $scope.words.push("hello");
      };

      this.sayHowdy = function() {
        $scope.words.push("howdy");
      };

      this.sayHi = function() {
        $scope.words.push("hi");
      };
    },

    link: function(scope, element){
      element.bind("mouseenter", function() {
        console.log(scope.words);
      });
    }
  }
});

Here, the welcome directive has a controller defined in it that will be used as an API for other directives to interact with it.

Next, we set up another directive within the app to interact with the welcome directive:

.directive("hello", function() {
  return {
    require: "welcome",
    link: function (scope, element, attrs, welcomeCtrl) {
      welcomeCtrl.sayHowdy();
    }
  };
 })

Here, we require the welcome controller, which gives us access to the controller (located in the foreign directive) in this directive’s linking function through an additional link function parameter - here, welcomeCtrl.

Note: the last parameter, which is the required controller, does not have a required name convention.

Adding in two more directives, “howdy” and “hi”:

.directive("howdy", function() {
  return {
    require: "welcome",
    link: function (scope, element, attrs, welcomeCtrl) {
      welcomeCtrl.sayHowdy();
    }
  };
 })

.directive("hi", function() {
  return {
    require: "welcome",
    link: function (scope, element, attrs, welcomeCtrl) {
      welcomeCtrl.sayHi();
    }
  };
 });

Now, each of these directives are tied to the welcome controller’s API methods.

We can now use them to alter the element directive:

<body ng-app="greetings">
  <welcome hello howdy hi>Say something!</welcome>
</body>

As intended, the individual attribute directives are able to interact with the element directive’s controller.

Isolate scope

However, with multiple instances of the welcome directive:

<body ng-app="greetings">
  <welcome hello howdy hi>Say something!</welcome>
  <welcome hi>Only Hi!</welcome>
</body>

Though the two element directives have different sets of directive attributes, each instance is evaluated sequentially. Since the scope is shared between the two element directives, the welcome directive takes on the form of whichever instance came last.

The solution is to provide the welcome directive with an isolate scope for each instance:

angular.module('greetings', [])
.directive("welcome", function() {
  return {
    restrict: "E",
    scope: {},
    controller: function($scope) {
      $scope.words = [];

This way, the scope for each directive is local only to that directive instance.