7

I cannot make nested transclusion work.

There are two directives, both of which declare they will transclude their content. When I nest them, the inner doesn't have any content.

Here is this fiddle, that demonstrates my problem.

Here is the code:

function Ctrl($scope) {
  $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
}

angular.module('transclude', [])
 .directive('outer', function(){
    return {
      restrict: 'E',
      replace: true,
      transclude: true,
      scope: {},
      template: '<div style="border: 1px solid black;">' +
                '<div>Outer</div>' +
                '<inner ng-transclude></inner>' +
                '</div>'
    };
 }).directive('inner', function(){
     return {
         restrict: 'E',
         transclude: true,
         replace: true,
         template :'<div style="border: 1px solid red;">' +
                   '<div>Inner</div>' +
                   '<div ng-transclude></div>' +
                   '</div>'
     };
 });

2 Answers 2

9

You should ng-transculde inside the inner directive since transclude replaces the inner html

angular.module('transclude', []).directive('outer', function(){
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        template: '<div style="border: 1px solid black;">' +
            '<div>Outer</div>' +
            '<inner><div ng-transclude></div></inner>' +
            '</div>'
        };
});

No change to inner directive needed.

I have updated the fiddle here

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. Now it seems obvious. :)
One thing to note is that this approach adds extra markup which, if you're doing a deep nesting, can get a bit messy. transclude:element avoids that. But for your use either is probably good.
@KayakDave If we remove this extra markup inner html of outer div would not get transcluded whether you use transclude:element. Let me know if I am wrong. Thanks :)
Yea, oops- I was thinking about a rather more complex and different scenario I had just been looking at. For your situation, you're right.
0

Another way to do this, which can be useful in self contained components is displayed in this JSFiddle

.directive('outer', function(){
    return {
      restrict: 'E',
      replace: true,
      transclude: true,
      template: '<div style="border: 1px solid black;">' +
                '<div>Outer</div>' +
                '<inner></inner>' +
                '</div>'
    };
 })
.directive('inner', function(){
     return {
         restrict: 'E',
         replace: true,
         require: '^outer',
         template :'<div style="border: 1px solid red;">' +
                   '<div>Inner</div>' +
                   '<div ng-transclude></div>' +
                   '</div>'
     };
 });

This will pass the transclude: true down the dom tree to the inner directive.

The downside of this is that the cannot be used by itself and in the jsfiddle it throws an ngTransclude: Orphan Directive Error

Because of this I require that the inner directive be a child of the outer directive, that way it will always have the transclusion passed down to it.

This is really nice to break up large directives into smaller ones.

Comments

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.