Being wrapped by a directive, how can I access its scope?
-
21-12-2019 - |
Question
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?
Solution
You forgot about two things:
- By default AngularJS uses attrubute restriction, so in your case in directive definition you should specify
restrict: "E"
- 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.
OTHER TIPS
There are couple of problems in your code.
- The default restrict option is
A
for attribute so anyways your directive will not be compiled because you are using it as an element. Userestrict: 'E'
to make it work. 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.
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.