repeat not work inside a transclusion?
Okay, this may seem somewhat esoteric, but I am trying to solve a particular issue with a directive I have written: https://github.com/michaelbromley/angularUtils/issues/37
Here is a simplified version of what is going on.
This works:
I have a directive that delegates to ng-repeat by dynamically adding an ng-repeat
attribute to the element during the compile stage, and then compiles that element:
myApp.directive('repeatDelegator', function($compile, $timeout) {
return {
compile: function(element, attrs){
attrs.$set('ngRepeat', attrs.repeatDelegator); //Add ng-repeat to the dom
element.removeAttr('repeat-delegator'); // remove the repeat-delegator to prevent infinite recursion of compilation
var compiled = $compile(element, null);
return function(scope, element, attrs){
compiled(scope);
};
}
}
});
This is how the directive is called:
<ul>
<li repeat-delegator="item in items">{{item}}</li>
</ul>
This works fine - see the first example here: http://plnkr.co/edit/oWd3rGAulsxoeSqffxMU?p=preview
However, when the repeat-delegator
is put inside any other directive that uses transclusion, it does not work.
This does not work. Why?
Here is a basic directive that does nothing but causes transclusion:
myApp.directive('transcluder', function() {
return {
restrict: 'AE',
transclude: true,
scope: {},
template: '<div ng-transclude></div>'
};
});
So when we call the repeat-delegator
directive inside this transclusion, it fails and nothing shows up:
<transcluder>
<ul>
<li repeat-delegator="meal in meals">{{meal}}</li>
</ul>
</transcluder>
This is illustrated in the second example: http://plnkr.co/edit/oWd3rGAulsxoeSqffxMU?p=preview
What I know so far:
I have spent some hours stepping through the Angular.js source as this executes to try to figure out why it fails inside the transclusion, but I can't get to the bottom of it.
In the broken (transcluded) version, when I see the ngRepeat being compiled, the $scope seems to be correct (it is a child $scope of the main controller $scope, since the transclusion causes a new child $scope to be created). You can write "scope.items" in the console and see the list of items.
I am guessing something like this is happening:
$template
var, for later insertion back into the DOM. ng-repeat
to compile against a clone of the <li>..</li>
node, which never actually gets attached back to the DOM? I'm not sure though. It's a really tricky problem, and any help would be very much appreciated!
Okay, after a day spent hacking away at the Angular.js source in dev tools, I figured out what was wrong here, and my guess above was basically right.
The trouble was that the repeat-delegator
directive would get compiled against the detached clone, so effectively the ng-repeated elements would be appended to a lost piece of DOM that would never get appended back to the body of the page.
The solution was fairly simple: move the compilation of the repeat-delegator's delegated ng-repeat into the linking function (rather that in the compile stage, where it was originally).
Doing this means that when the ng-repeat gets compiled, it is done against the correct DOM node which is now safely attached to the DOM below the transcluded directive.
myApp.directive('repeatDelegator', function($compile, $timeout) {
return {
compile: function(element, attrs){
attrs.$set('ngRepeat', attrs.repeatDelegator); //Add ng-repeat to the dom
element.removeAttr(attrs.$attr.repeatDelegator); // remove the repeat-delegator to prevent infinite recursion of compilation
return function(scope, element, attrs){
var compiled = $compile(element);
compiled(scope);
};
}
}
});
链接地址: http://www.djcxy.com/p/95238.html
下一篇: 重复在一个跨越里面不工作?