1

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?

2
  • I couldn't get what you're going for to work... but alternatively, I did get it to work without the transclude by just putting the other directive in the template... Here's the plunkr in case that's helpful at all plnkr.co/edit/v7oFnukZxHMEi3xasFmc?p=preview Commented May 31, 2016 at 16:34
  • That's okay if I only have one use-case, but in my uses I'll have to make a copy of this directive for every use-case I have which defeats the purpose of a directive Commented Jun 1, 2016 at 7:17

1 Answer 1

1

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

3 Comments

I get that error thrown or else told that transcludeFn is not a function.
@casraf you still have to use transclude:true in your repeatContents directive. Only change ng-transclude to custom-transclude. Hee is a working plunker. plnkr.co/edit/jl8veC?p=preview
It seems a little clearer to me when you take the "link" out of the repeatContents directive in the working demo above. That demonstrates what is actually happening, and why you see the additional "Other item:" at the end.

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.