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

18,186

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.

Share:
18,186
ivarni
Author by

ivarni

Hi, I'm dead!

Updated on June 08, 2022

Comments

  • ivarni
    ivarni about 2 years

    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?