【发布时间】:2013-12-16 17:54:42
【问题描述】:
这里有一些代码:link
我正在尝试创建一个指令,将其子项包装在一些样板文件中。但是如果孩子们有ng-if控制他们的外表,那么“嵌入”就不起作用了。好吧,确实如此,但正如您所见,ng-if 逻辑没有正确通过。
我想知道如何修复它,以及 Angular 文档中描述的位置(如果有的话)。
【问题讨论】:
标签: angularjs angularjs-directive transclusion
这里有一些代码:link
我正在尝试创建一个指令,将其子项包装在一些样板文件中。但是如果孩子们有ng-if控制他们的外表,那么“嵌入”就不起作用了。好吧,确实如此,但正如您所见,ng-if 逻辑没有正确通过。
我想知道如何修复它,以及 Angular 文档中描述的位置(如果有的话)。
【问题讨论】:
标签: angularjs angularjs-directive transclusion
问题是 Angular 最初将 ngIf 替换为注释,用于跟踪条件代码的放置位置。举个例子最容易看出。
您的 HTML:
<div control-group>
<label>Test</label>
<input type="text" ng-model="editing.name" />
<span class="text-error" ng-if="editing.name.length != 3"> Name must be 3 characters </span>
</div>
在您的 transclude 函数的 cloned 变量 (transclude(function (cloned) {) 中看起来像这样:
<div control-group>
<label>Test</label>
<input type="text" ng-model="editing.name" class="ng-valid ng-dirty">
<!-- ngIf: editing.name.length != 3 -->
</div>
因此,您要过滤的类 text-error 的元素(如下)不在 cloned 中。只是评论在那里。
var inputsAndMessages = cloned.filter('input, button, select, .text-error');
由于您只包含与上述过滤器匹配的元素,因此ngIf 注释将丢失。
解决方案也是过滤 cmets 并将它们添加到您的追加中(因此 Angular 保持它对 ngIf 的引用点)。一种方法是用这个替换上面的内容(使用 html 注释是节点类型 8 的事实)
var messages = cloned.filter(function(){ return this.nodeType == 8; }); //comments
var inputs = cloned.filter('input, button, select')
var inputsAndMessages = inputs.add(messages);
【讨论】:
ng-if,所以我需要自己设置指令定义terminal: true和$compile。这样我就可以在任何 ng-if 被编译并变成评论之前重新排列元素。
您需要使用ng-transclude 指令告诉指令将子元素放置在何处:(plnkr)
template: "<div class='control-group' ng-transclude>" +
"<label class='control-label' for=''></label>" +
"<div class='controls'></div>" +
"</div>",
来自文档:
为使用嵌入的最近父指令的嵌入 DOM 标记插入点的指令。
该指令所在元素的任何现有内容都将在插入嵌入内容之前被删除。
我不确定您的意图究竟是什么,因为您在模板中和 HTML 中都有 input 和 label。您可能想将您的 ng-transclude 放在其他地方。
【讨论】:
ng-transclude,因为我想在模板中的不同点嵌入我的输入子元素。所以我需要使用更灵活的translude 函数。我可能应该将这一点添加到我的问题中。