Reputation: 2871
I'm trying to make a set of directives so i can repeat through a large list of data without creating many scopes, because the scopes take many seconds to clean up by Chrome's garbage collection.
The issue in my solution is that I call $compile
in the for loop, yet the directive inside the $compile'd html isn't being evaluated for every iteration of the loop. it's only being evaluated at the end.
console.log output:
lscope.name: jason app.js:20
lscope.name: fred app.js:20
lscope.name: anthony app.js:20
lscope.name: balory app.js:20
[div, jquery: "2.1.1", constructor: function, selector: "", toArray: function, get: function…] app.js:25
lessif: true
Code:
app.controller('MainCtrl', function($scope) {
$scope.names = ['jason', 'fred', 'anthony', 'balory'];
});
app.directive('scopelessRepeat', function($compile) {
console.log('scopeless repeat called');
return {
transclude: 'element',
restrict: "AE",
scope: false,
link: function (lscope, lelement, lattrs, lcontroller, ltransclude) {
console.log('attrs: ', lattrs);
var root = $('<div></div>');
ltransclude(lscope, function(transHtml) {
for(var i=0; i!=lscope[lattrs.items].length; ++i){
lscope[lattrs.key] = lscope[lattrs.items][i];
console.log('lscope.name: ', lscope.name);
$compile(transHtml.contents())(lscope, function cloneFn(cloneHtml) {
root.append(cloneHtml);
});
}
console.log(root);
lelement.after(root);
});
},
};
});
app.directive('lessIf', function($compile) {
return {
transclude: 'element',
restrict: "AE",
scope: false,
priority: 1000,
//link: function (lscope, lelement, lattrs, lcontroller, ltransclude) {
controller: function ($scope, $element, $attrs) {
console.log('lessif: ', $scope.$eval($attrs['lessIf']));
if($scope.$eval($attrs['lessIf']))
$element.replaceWith($compile($element)($scope));
else
$element.replaceWith(' ');
},
};
});
Why is my inner directive not being evaluated every iteration loop? (p.s. yes I know about bind-once, but it doesn't help the garbage collection issue, also the dev isn't getting back to me about have multiple contexts for a bind-once, so I have to roll my own)
Upvotes: 0
Views: 282
Reputation: 54543
Do it like this, you need to put the ltransclude(..)
inside the loop.
for (var i = 0; i != lscope[lattrs.items].length; ++i) {
ltransclude(lscope, function(transHtml) {
lscope[lattrs.key] = lscope[lattrs.items][i];
$compile(transHtml.contents())(lscope, function cloneFn(cloneHtml) {
root.append(cloneHtml);
});
lelement.after(root);
});
}
Upvotes: 1