Can someone explain the root cause behind the following behavior?
If a directive with isolate scope scope: {}
has a root element with ng-repeat
AND replace: true
then it "breaks" the isolate scope, meaning that the isolate scope is not accessible/visible from within the directive, and the directive starts receiving variables from the outer scope.
Here's the minimally reproducible example I could make:
app.controller('MainCtrl', function($scope) {
$scope.name = 'MainCtrl';
});
app.directive("foo", function(){
return {
replace: true,
scope: {},
template: "<div ng-repeat='item in [1]'>{{name}}</div>",
controller: function($scope){
$scope.name = "foo";
}
};
});
The following view would render "MainCtrl":
<div ng-controller="MainCtrl">
<foo></foo>
</div>
Adding either a non-ng-repeat
-able root to the template OR setting replace: false
renders the expected result "foo".
It does not just happen for ng-repeat, this seems to happen for any other directives that creates a scope like
ng-if
as well. And it seems like, this is because the directive's isolated scope gets overwritten by the ng-repeat's child scope. And because ofreplace:true
option ng-repeat becomes a part of the directive source element i.e<foo></foo>
and the child scope of ng-repeat is calculated from the ultimate parent scopeMainCtrl
(Which appears to be wrong) and this causes the entire directive template to be bound to the child scope of controller and any interpolations are evaluated against that scope. Hence you see main controller's scope being expanded in the directive. This seems like a bug.