Is there any way to just use a child directive as a placeholder for holding content?

I am new to Angularjs. Want to see if there is any way to just use a child directive as a placeholder for holding content but for really rendering?

I don't want to do rendering in the child directive because I want to let the parent to do everything. So I can have some other special logics in the parent directive.

  angular.module('components', []).
  directive('tabs', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: {},
      controller: function($scope, $element) {
        var panes = $scope.panes = [];

        $scope.select = function(pane) {
          angular.forEach(panes, function(pane) {
            pane.selected = false;
          });
          pane.selected = true;
        }

        $scope.createPane = function() {
          var pane = panes[panes.length-1];
          var clonedPane = Angular.copy(pane);
          panes.push(clonedPane);
        }

        this.addPane = function(pane) {
          if (panes.length == 0) $scope.select(pane);
          panes.push(pane);
        }
      },
      template:
        '<div class="tabbable tabs-left">' +
          '<ul class="nav nav-tabs">' +
            '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
              '<a href="" ng-click="select(pane)">{{pane.title}}</a>' +
            '</li>' +
            '<li ng-class="addLink"><a ng-click="createPane()"><i class="icon-plus"></i> tab</a></li>' +
          '</ul>' +
          '<div class="tab-content">' + 
            '<div ng-repeat="pane in panes" class="tab-pane" ng-class="{active: selected},{{pane.pclass}}" id="{{pane.id}}">' + 
              '{{ pane.content }}' +
            '</div>' +
          '</div>' +
        '</div>', 
        replace: true
    };
  }).
  directive('pane', function() {
    return {
      require: '^tabs',
      restrict: 'E',
      scope: { title: 'bind', pclass: 'bind', id: 'bind' },
      link: function(scope, element, attrs, tabsCtrl) {
        var text = element.text();
        tabsCtrl.addPane({
          title: scope.title, 
          pclass: scope.pclass, 
          id: scope.id, 
          content: text
        });
      }
    };
  })

Corresponding html code:

<tabs>
  <pane title="tab 1" id="tab1" pclass="tab">
    hello
  </pane>
  <pane title="tab 2" id="tab2" pclass="tab">
    world
  </pane>
</tabs>

I tried something like the above but nothing is pushed into panes. Seems like the link function of the child directive (pane) is never called. So as a result, only the link for adding tab is displayed.

Any ideas?

Thanks!

The easiest (though sort of annoying) way to approach this would be to have a template for each pane.

In html:

<tabs>
  <pane title="tab 1" id="tab1" pclass="tab" template="pane1-templ">
  </pane>
  <pane title="tab 2" id="tab2" pclass="tab" template="pane2-templ">
  </pane>
</tabs>
<script type="text/ng-template" src="pane1-template">hello</script>
<script type="text/ng-template" src="pane2-template>wolrd</script>

In your directive:

'<div class="tab-content">' + 
    '<div ng-repeat="pane in panes" class="tab-pane" ng-class="{active: selected},{{pane.pclass}}" id="{{pane.id}}">' + 
         '<div ng-include src="pane.template"></div>' +
    '</div>' +
'</div>'

Or.. have you tried doing this to fix it?

In pane:

var html = elm.html();
//...
pane.html = html;

In tabs:

<div ng-bind-html-unsafe="pane.html"></div>

Perhaps the reason why it is not working is because in your child directive you have no template.. Without a template, the directive does not know where and how to render the directive..

What you could do is have something like

template : '<div style="display:none;" ng-transclude></div>'

in your child template..

and your element.text() should still work!

Without a template.. the linking function would never get the 'element' so your child directive will fail right there..

With the template above it should work..