Search code examples
serviceangularjsdirectiveconcept

AngularJS directive communication not having same parent


Let's imagining that I have a directive that contains some data and I want to interpolate it somewhere else in a second component (directive or else), without having a controller linking them.

For example, take the zippy of angularjs webpage, but instead of having <div ng-controller="Ctrl3"> bidding the data from the input to the zippy directive, we have two separate components:

    <!-- first component with data -->
    <div ng-controller="aCtrl">

    Title: <input ng-model="title"> <br>
    Text: <textarea ng-model="text"></textarea>
    </div>

    <hr>
    <!-- a second component wanting to show the data -->
    <div class="zippy" zippy-title="Details: {{title}}...">{{text}}</div>

My question is then how can I link them nicely in Angularjs?

I tried to pass through a service, registering the data changes, and then tried unsuccessfully to bind it with my DOM through an injection into a directive or through a controller.

( I want to display data contained in a directive in an another directive "window", but I don't want to wrap all my code with a controller just to bind the data)

Is there a way to do it nicely?


Solution

  • Here is one solution using a service that triggers a custom event on $rootScope, then listens for event in controller of directive'

    app.factory('SharedData',function($rootScope){
        return{
            data:{text : 'World', title:'Foo bar'},
            upDate:function(prop,val){
               this.data[prop]=val;
               $rootScope.$emit('dataUpdate',prop)
            }
        }
    });
    
    
    app.controller('aCtrl', function ($scope,SharedData) {
        angular.forEach(SharedData.data,function(value,key){
            $scope[key] = value;
            $scope.$watch(key,function(){
                SharedData.upDate(key,$scope[key]);
            });
        });
    });
    
    app.directive('zippy',function($rootScope,SharedData){
        return{
            restrict:'C',
            replace:false,
            scope:{},
            controller:function($scope) {
                $rootScope.$on('dataUpdate',function(event,prop) {
                    $scope[prop] = SharedData.data[prop];
                });
            }
        }
    });
    

    Plunker Demo