0

I have two directives, lets say:

angular.module('app').directive('directiveA', directiveA);

    function directiveA(){
        return {
            restrict: 'E',
            transclude: true,
            scope: {},
            templateUrl: 'directiveA.html',
            controller: function($scope){
                $scope.test="test data";
            }
        };
    }

And second one:

angular.module('app').directive('directiveB', directiveB);

function directiveB(){
    return {
        restrict: 'E',
        require: '^directiveA',
        transclude: true,
        scope: {},
        templateUrl: 'directiveB.html',
        link: function(scope, elem, attrs, directiveAController) {
            console.log("directiveB linked");
        }
    };
}

HTML for directiveA:

<div>
<!-- something here -->
    <div ng-transclude></div>
</div>

HTML for directiveB:

<div>{{test}}</div>

And I wanna use them like this:

<directive-a>
     <directive-b></directive-b>
</directive-a>

How can I make them communicate with each other using require and ng-transclude and have both templates rendered ? For example I would like to print test variable from directiveA in directiveB template. I am new to directives and transclusion.

Bouncer00
  • 123
  • 1
  • 4
  • 12

1 Answers1

0

You have some options to do the communication:

  1. With $broadcast or $emit depending on your scope. See this SO question. Emitting to $rootScope is good here because all childs can listen for events.
  2. Use a callback function (works only for the child directive).
  3. Observer pattern.

See my demo code below or in this jsfiddle.

angular.module('demoApp', [])
 .controller('mainController', function($scope) {

})
 .service('interDirCom', function() {
    // observer pattern
      var self = this;
    
   angular.extend(this, {
                subscribers: [],
                subscriberCount: 0,
            newSubscriber: function(callback) {
                return {
                    id: self.subscriberCount++,
                    notify: callback
                };
            },
            subscribe: function(callback) {
                //add listener
                var subscriber = self.newSubscriber(callback);
                self.subscribers.push(subscriber);
            },
            notify: function(message){
                console.log('notify', this, self, self.subscribers);
                angular.forEach(self.subscribers, function(subscriber) {
                    console.log(subscriber, message);
                    subscriber.notify(message);
                });
            }
        });
     //return service;
 })
    .directive('directiveA', directiveA)
    .directive('directiveB', directiveB);

function directiveA() {
    return {
        restrict: 'E',
        transclude: true,
        scope: {},
        templateUrl: 'directiveA.html',
        controller: function ($scope, $rootScope, interDirCom) {
            
            interDirCom.subscribe(function(message) {
                //console.log('callback of subscriber called');
             $scope.test2 = message;
            });
            
            $scope.test = "test data";
            this.test = 'hello from controller A in dir. B';
            
            $rootScope.$on('dirB:test', function(evt, data) {
                console.log('received event', data);
             $scope.test = data.message;
            });
            
            this.callback = function(message) {
                $scope.test2 = message;
            };
        }
    };
}

function directiveB(interDirCom) {
    return {
        restrict: 'E',
        require: '^directiveA',
        transclude: true,
        scope: {},
        templateUrl: 'directiveB.html',
        link: function (scope, elem, attrs, directiveACtrl) {
            console.log("directiveB linked");
            //scope.test = "hello from B";
            scope.test = directiveACtrl.test;
            
            scope.$emit('dirB:test', {message: 'Hello from directive B in dir. A with a $emit to $rootScope'});
            directiveACtrl.callback('I am added with a callback function from dir. B. to dir. A');
            interDirCom.notify('Message from dir. B with observer pattern');
            console.log(interDirCom);
        }
    };
}
directive-b div{
    background-color: green !important;
}

directive-a>div{
    background-color: lightgray;
    border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="mainController">
    <script type="text/ng-template" id="directiveA.html">
        <div>
            <h1>Directive A</h1>
            {{test}}<br/>
            {{test2}}
            <!-- something here -->
            <div ng-transclude></div>
        </div>
    </script>
    <script type="text/ng-template" id="directiveB.html">
        <div>
        <h1>Directive B</h1>
        <div>{{test}}</div>
            <div>{{test2}}</div>
        </div>
    </script>
    <directive-a>
        <directive-b></directive-b>
    </directive-a>
</div>
Community
  • 1
  • 1
AWolf
  • 8,770
  • 5
  • 33
  • 39