Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ng-transclude and ng-include in a nested angular directive

TL;DR: On this plunker, why does the second directive not render the included template?

This example is simplified, but I actually have a usecase where doing what I am about to attempt makes sense.

I have an Angular directive that uses ng-include to wrap a provided template into some other HTML using ng-include and and ng-transclude. It works fine on its own.

.directive('content', [function() {
    return {
        restrict: 'E',
        transclude: true,
        replace: true,
        controller: 'contentCtrl',
        template: '' +
          '<div class="foo">' +
          '  <div ng-transclude></div>' +
          '</div>',
        scope: {
        }
    };  
}])

.directive('contentInner', [function() {
    return {
        restrict: 'E',
        require: '^content', 
        transclude: true,
        replace: true,
        scope: {
        },
        template: '' +
          '<div class="body">' +
          '  <div class="close" ng-click="close()">' +
          '    <i class="icon-remove-sign"></i>' +
          '    <span>Close</span>' +
          '  </div>' +
          '  <div ng-transclude ></div>' +
          '</div>',
        link: function(scope, element, attrs, controller) {
          scope.close = function() {
              controller.close();
          };
        }
    };
}])

But then I have another directive that is trying to use this first directive and that's where it breaks down and fails silently.

.directive('box', ['$compile', function($compile) {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            template: '@'
        },
        template: '' +
          '<div>' +
          '  <content>' +
          '    <content-inner>' +
          '      <div ng-include ng-src="{{template}}"/>' +
          '    </content-inner>' +
          '  </conent>' +
          '</div>',
        link: function(scope, element) {
          //$compile(element)(scope);
        }
    };
}]);

Looking at the generated source I can see that it looks like this

<div template="'template.html'">
  <div class="foo">
    <div ng-transclude="">
      <div class="body ng-scope">
        <div class="close" ng-click="close()">
          <i class="icon-remove-sign"></i>
          <span>Close</span>
        </div>
        <div ng-transclude="">
          <div ng-include="" ng-src="'template.html'" 
              class="ng-scope" src="'template.html'">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

So the reference to the template in the ng-include at the innermost level is there but it is not getting rendered. Plunker.

So where did my template go in the second directive?

like image 321
ivarni Avatar asked Aug 12 '13 12:08

ivarni


1 Answers

I think I managed to fix your problem, by changing two things. See it here: plunker.

When using "@" for a directive scope, the attribute is passed to the scope as a string, so you shouldn't put the value between simple quotes.

Also, I replaced <div ng-include ng-src="{{template}}"/> in the template with <div ng-include="template"/> because from the documentation, ng-include doesn't use src when used as an attribute (but I don't understand why it worked in your first example...)

Hope that helps anyway.

like image 118
Yann Avatar answered Nov 02 '22 20:11

Yann