When you need to exchange data between two custom directives without using a service, the ngModel directive can be used create a communication channel. Using this built in Directive you can pass data between custom directives as this example illustrates. For this technique to work certain conditions must be met:
1/ The directives must be enclosed within the same parent controller
2/ The custom directive attributes must be assigned to the same variable name

In the code sample on Plunker, we have two Phone Networks, Verizon and Sprint, representing the two custom directives. The phone type represents the data to be passed between the directives. The directives are named sprint-network and verizon-network and the parent controller is netController. The two directives are defined in the sprintModule.js file and they have separate template files: templatesprint.html and templateverizon.html.

netController is the parent controller which wraps the two directives within a common parent scope. And the samsung attribute in sprintNetwork directive is assigned to the phone scope variable. In the verizonNetwork directive, the iphone attribute gets assigned to the similar phone scope variable. These two scope variables belong to separate isolated scopes and would normally have different values. However using the ngModel directive through the require method in the verizonNetwork directive, the two variables are data bound. Placing the ^ character before ngModel makes the ngModel a required attribute in the verizonNetwork directive when it’s implemented in the index.html file. Using ? makes the attribute optional. Note that the link method in verizonNetwork directive takes ngModel as the fourth argument. To illustrate this technique, change the phone brand from the drop down in verizonNetwork (and click the “get phone” button) to update the phone scope variable in both directives.

var networkTwoApp = angular.module("networkApp", []);
networkTwoApp.controller("netController", function ($scope){
  $scope.phone = "Apple iPhone 5";
});

networkTwoApp.directive("sprintNetwork", function() {
  console.log("networkTwo");
  return {
    restrict: 'AE',
    scope:{
      samsung: "=",
     },

    templateUrl: "templatesprint.html",

    link: function(scope, element, attrs, ngModel) {

      ngModel.$setViewValue(scope.phone);

     ngModel.$viewChangeListeners.push(function(){
       console.log("sprint view change");
     });
    }

  };

});

networkTwoApp.directive("verizonNetwork", function () {

    return{
        restrict: 'AE',
        scope:{
          iphone: "=",

        },

        templateUrl: "templateverizon.html",
        require: '^ngModel',
        link: function (scope, element, attrs, ngModel) {
          scope.phone = "my phone";
          ngModel.$setViewValue(scope.phone);
          scope.showPhone = function(){
            ngModel.$setViewValue("setviewvalue");

            ngModel.$setViewValue(scope.phone);
            console.log("clicked");
          };
          scope.phonedata = "my phone is cool";

        }
    }

});