casraf
casraf

Reputation: 21694

AngularJS transclude scope in directive with ng-repeat

My goal is to have a directive, which I give contents to, and it repeats them X times. Just like ng-repeat, only I want to wrap it in other features such as limit toggle and extra elements outside the transcluded content.

For some reason, the transclusion has no access to the directive isolate scope, no matter what I try.

I've used the transclude function inside link, in several variations, to no avail. Here's a demo:

And here's the gist of the code:

app.directive('repeatContents', function() {
  return {
    scope: {
      items: '=repeatContents',
      limit: '=repeatLimit'
    },
    transclude: true,
    template: '<div ng-repeat="item in items">' +
                  '<em>Outside transclude: {{item}}</em><br />' +
                  '<ng-transclude></ng-transclude>' +
              '</div>',
    link: function(scope, el, attrs, ctrl, transclude) {
      transclude(scope, function(clone, scope) {
        el.append(clone);
      });
    }
  }
});

If you look at the plunkr, you will see that outside the transclusion {{item}} is available, but not inside. Regardless of the link function's contents which were supposed to take care of it. Any idea what I can do?

Upvotes: 1

Views: 672

Answers (1)

Joel Kornbluh
Joel Kornbluh

Reputation: 1437

transclude:true transcludes the content while keeping a reference to the scope where the content is transcluded from (In our case, repeat-contents will transclude <other-directive other-item="item"></other-directive> while keeping a reference to the outer scope. item is not defined in the outer scope and the fact that your isolated scope defines item is irrelevant to the outer scope.

If you just want to transclude the template without keeping a reference to it's original scope you can use the following diective instead of ng-transclude:

app.directive('customTransclude', function(){
    return {
        link: function(scope, element, attrs, ctrls, transcludeFn){
            if(!transcludeFn){
                throw 'Illegal use of custom-transclude directive! No parent directive that requires transclusion was found';
            }

            transcludeFn(scope, function(clone){
                element.empty().append(clone);
            });
        }
    };
});

and then in the template of your repeat-contents directive you can use it like this:

<div ng-repeat="item in items">
    <em>Outside transclude: {{item}}</em><br/>
    <custom-transclude></custom-transclude>
</div>

Upvotes: 1

Related Questions