在父模板

时间:2015-05-24 16:38:01

标签: angularjs angularjs-directive

我正在建立一个名为card的指令。我想这样使用它:

<card theme="light">
    <card-header>
        <h2>Hello World</h2>
    </card-header>
    <card-options>
        <button class="btn btn-default">
            <i class="fa fa-pencil-square-o"></i>
        </button>
        <button class="btn btn-danger">
            <i class="fa fa-trash-o"></i>
        </button>
    </card-options>
    <!-- more will be added later, such as card-body -->
</card>

当编译时,我希望它能产生这个DOM:

<div class="card card-light">
    <!-- cardHeader class uses flexbox and is expecting
         only two child elements -->
    <div class="cardHeader">
        <!-- this div is the first child and should contain the header -->
        <div>
            <h2>Hello World</h2>
        </div>

        <!-- this div is the second child and should contain the options -->
        <div>
            <button class="btn btn-default">
                <i class="fa fa-pencil-square-o"></i>
            </button>
            <button class="btn btn-danger">
                <i class="fa fa-trash-o"></i>
            </button>   
        </div>
    </div>
</div>

卡片模板:

<div class="card card-{{cardVM.theme}}" ng-transclude>
</div>

卡片头模板:

<div class="cardHeader">
    <!-- Header goes here -->
    <div ng-transclude></div>

    <!-- Options go here... but how? -->
    <div></div>
</div>

我怀疑我可能必须将cardOptions元素传递给父卡,然后从cardHeader中绑定到它?

<div class="cardHeader">
    <!-- Header goes here -->
    <div ng-transclude></div>

    <!-- Options go here -->
    <div>
        {{$parent.optionsElem}}
    </div>
</div>

我不确定它会起作用,如果确实如此,那似乎很麻烦且效率低下。

有更简单的方法吗?

1 个答案:

答案 0 :(得分:1)

link函数的第5个参数是transclude函数,允许您手动转换托管指令的元素的内容。

ng-transclude实际上是以下行为的快捷方式:

link: function(scope, element, attrs, ctrls, transcludeFn){
   transcludeFn(function(clonedContents){
      element.append(clonedContents);
   }
}

它转换整个内容,将其链接到外部作用域,并将其放在ng-transclude元素中。

因此,在您的情况下,使用ng-transclude将无效。相反,您需要手动转换并识别要放在哪里的部件。如果您在模板中使用占位符元素,它会有所帮助:

.directive("card", function(){
  return {
    transclude: true,
    scope: {...},
    // simplified template for illustrative purposes:
    template: '<div>\
                 <div class="header">\
                    <card-header-placeholder></card-header-placeholder>\
                 </div>\
                 <div class="body">\
                    <card-body-placeholder></card-body-placeholder>\
                 </div>\
               </div>',
    link: function(scope, element, attrs, ctrls, transcludeFn){
       transcludeFn(function(clone){
          var root = angular.element("<root>").append(clone);
          element.find("card-header-placeholder")
                 .replaceWith(root.find("card-header"));

          element.find("card-body-placeholder")
                 .replaceWith(root.find("card-body");
       });
    }
  }
);