0

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)

Plnkr:

1 Answer 1

1

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);
    });
  }
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that technically worked. I updated the plnkr, but now my second directive just doesn't show up [the console logs are printing, so it IS being evaluated]. I'm currently just trying to show text... it works outside of directives. I'm wondering if it has to do with the order of compiling the transcluded html, because I noticed the lesss-if is compiled AFTER the $compile function is called in scopeless-repeat; it appears to happen when the transclusion function returns.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.