3
votes

How can I access the directive's isolate scope in the directive's body? My DOM looks like this:

<div ng-app="app">    
    <directive>
        <p>boolProperty: {{boolProperty|json}}</p>
    </directive>
</div>

The boolProperty is assigned inside the directive's link function:

angular.module("app", []).directive("directive", function() {
    return {
        scope: {},
        link: function($scope) {
            $scope.boolProperty = true;
        }
    };
});

The problem is, the child <p> inside the directive binds to the directive's parent scope, not the directive's isolated scope. How can I overcome this?

Click here for jsFiddle.

3

3 Answers

3
votes

There are couple of problems in your code.

  1. The default restrict option is A for attribute so anyways your directive will not be compiled because you are using it as an element. Use restrict: 'E' to make it work.
  2. As per the documentation, the scope of the transcluded element is not a child scope of the directive but a sibling one. So boolProperty will always be undefined or empty. So you have to go up the scope level and find the proper sibling.

    <div ng-app="app">
       <directive>
        <p>boolProperty: {{$parent.$$childHead.boolProperty}}</p>
        </directive>
    </div>
    

and need to use transclusion in the directive as:

angular.module("app", []).directive("directive", function() {
    return {
        restrict: 'E',
        scope: {},
        transclude: true,
        template: '<div ng-transclude></div>',
        link: function(scope) {
            scope.boolProperty = true;
        }
    };
});

However, this approach is not advisable and break later If you add a new controller before the directive because transcluded scope becomes 2nd sibling unlike 1st as before.

<div ng-app="app">
    <div ng-controller="OneCtrl"></div>
    <directive>
        <p>boolProperty: {{$parent.$$childHead.boolProperty || $parent.$$childHead.$$nextSibling.boolProperty}}</p>
    </directive>
</div>

Here is the Working Demo. The approach I mentioned is not ideal so use at your own risk. The @CodeHater' s answer is the one you should go with. I just wanted to explain why it did not work for you.

1
votes

You forgot about two things:

  1. By default AngularJS uses attrubute restriction, so in your case in directive definition you should specify restrict: "E"
  2. You should use child scope, but not isolated. So set scope: true to inherit from parent view scope.

See updated fiddle http://jsfiddle.net/Y9g4q/1/.

Good luck.

1
votes

From the docs:

As the name suggests, the isolate scope of the directive isolates everything except models that you've explicitly added to the scope: {} hash object. This is helpful when building reusable components because it prevents a component from changing your model state except for the models that you explicitly pass in.

It seems you would need to explicitly add boolProperty to scope.

<div ng-app="app" ng-controller="ctrl">    
    <directive bool="boolProperty">
        <p>boolProperty: {{boolProperty|json}}</p>
    </directive>
</div>

JS

angular.module("app", []).controller("ctrl",function($scope){
    $scope.boolProperty = false;
}).directive("directive", function() {
    return {
        restrict:"E",
        scope: {boolProperty:'=bool'},
        link: function($scope) {
            $scope.boolProperty = "i'm a boolean property";
        }
    };
});

Here's updated fiddle.