fatlinesofcode
fatlinesofcode

Reputation: 1667

How can I pass variables from an isolated scope directive to a child?

I have two isolated scope directives. Ideally I like both to work independently and not require any custom templates. The first directive is going to be page scroll watcher, when it hits a certain point I want it to trigger an update in the other directive. Is it possible for a child directive to watch a variable in the parent directive?

I've created a simple plunkr to illustrate the issue, http://plnkr.co/edit/wwfBzmemyrj1r1R54riM?p=preview

    /*
 <div ng-outer>Outer directive {{myvar}}
      <div ng-inner="myvar">Inner directive</div>
    </div>
    */
app.directive('ngOuter', [ '$timeout', function ($timeout) {
    var directive = {
        restrict: 'A'
        ,scope:{}
    }
    directive.link = function (scope, element, attrs) {
        $timeout(function(){
          scope.myvar = "test 001"
        },1000)
    }
    return directive;

}]);

app.directive('ngInner', [ function () {
    var directive = {
        restrict: 'A'
        ,scope:{ data: '=ngInner',  myvar: '=myvar' }
    }
    directive.link = function (scope, element, attrs) {
        scope.$watch('data', function(newVal, oldVal){
          if(newVal)
          element.text("new inner val", newVal);
        });
          scope.$watch('myvar', function(newVal, oldVal){
          if(newVal)
          element.text("new myvar", newVal);
        });


    }

    return directive;

}]);

Upvotes: 4

Views: 2234

Answers (2)

UserNeD
UserNeD

Reputation: 1509

First approach of passing variable from parent directive to the child is by using an 'attr' in child scope with '@' and initialize it in parent controller as following:

var app = angular.module('app', []);

app.directive('ngOuter', [ '$timeout', function ($timeout) {
    return{
       restrict: 'E',
       scope:{},
       template: '<ng-inner attr="{{myvar}}">Inner directive {{myvar}}</ng-inner>',
       controller: ['$scope', function($scope) {
            $scope.myvar = "test 001";
       }],
       link: function (scope, elem, attrs) {

       }
    }
}]);

app.directive('ngInner', [ function () {
    return{
       restrict: 'E',
       scope:{'attr' : "@"},
       link: function (scope, element, attrs) {
           console.log(scope.attr);
       } 
    }
}]);

html:

    <ng-outer></ng-outer>

2nd approach is utilizing a function in a parent controller which returns the "myvar" value and call that function in child directive:

app.directive('ngOuter', [ '$timeout', function ($timeout) {
    return{
        restrict: 'E',
        scope:{},
        template: '<ng-inner attr="{{myvar}}">Inner directive {{myvar}}</ng-inner>',
        controller: ['$scope', function($scope) {
            $scope.myvar = "test 001";
            this.getMyvar = function() {
                return $scope.myvar;
            };
        }],
        link: function (scope, elem, attrs) {

       }
   }

}]);

app.directive('ngInner', [ function () {
    return{
        restrict: 'E',
        require: '^ngOuter',
        scope:{'attr' : "@"},
        link: function (scope, element, attrs, parentDirCtrl) {
            console.log(parentDirCtrl.getMyvar());
        } 
    }

}]);

3rd Approach: you can inject a service to both inner and outer directives.Then use the service.

var app = angular.module('app', []);


app.service('myService', [
  function() {
    var service = {
      myvar: 'test001',
      setMyVar: function(value) {
        this.myvar = value;
      },
      getMyVar: function() {
        return this.myvar;
      }
    }
    return service;
  }
]);



app.directive('ngOuter', ['$timeout', 'myService',
  function($timeout, myService) {
    var directive = {
      restrict: 'A',
      scope: {}
    }
    directive.link = function(scope, element, attrs) {
      $timeout(function() {
        scope.myvar = myService.getMyVar();
      }, 1000)
    }
    return directive;

  }
]);

app.directive('ngInner', ['myService',
  function(myService) {
    var directive = {
      restrict: 'A',
      scope: {}
    }
    directive.link = function(scope, element, attrs) {
      var variable = myService.getMyVar();
      console.log("myvar", variable);
    }
    return directive;

  }
]);

Upvotes: 0

fatlinesofcode
fatlinesofcode

Reputation: 1667

Solved this issue by using

angular.element(element.parent()).isolateScope();

The child directive can access the scope of the parent directive and watch variables etc.

http://plnkr.co/edit/RAO6q81ZE4tClMDMiLFb?p=preview

Upvotes: 1

Related Questions