我有两个指令
app.directive('panel1', function ($compile) { return { restrict: "E", transclude: 'element', compile: function (element, attr, linker) { return function (scope, element, attr) { var parent = element.parent(); linker(scope, function (clone) { parent.prepend($compile( clone.children()[0])(scope));//cause error. // parent.prepend(clone);// This line remove the error but i want to access the children in my real app. }); }; } } }); app.directive('panel', function ($compile) { return { restrict: "E", replace: true, transclude: true, template: "<div ng-transclude ></div>", link: function (scope, elem, attrs) { } } });
这是我的观点:
<panel1> <panel> <input type="text" ng-model="firstName" /> </panel> </panel1>
错误:[ngTransclude:orphan]在模板中非法使用ngTransclude指令!找不到需要包含的父指令。元件:<div class="ng- scope" ng-transclude="">
<div class="ng- scope" ng-transclude="">
我知道panel1不是实际的指令。但是在我的实际应用程序中,我也遇到了这个问题。
我在http://docs.angularjs.org/error/ngTransclude:orphan上看到了一些解释。但是不知道为什么我在这里有这个错误以及如何解决它。
编辑 我创建了一个jsfiddle页面。先感谢您。
编辑
In my real app panel1 does something like this: <panel1> <input type="text> <input type="text> <!--other elements or directive--> </panel1>
结果=>
<div> <div class="x"><input type="text></div> <div class="x"><input type="text></div> <!--other elements or directive wrapped in div --> </div>
原因是当DOM完成加载后,Angular将遍历DOM并将所有指令转换为模板, 然后再 调用compile和link函数。
这意味着,当你打电话$compile(clone.children()[0])(scope)时,clone.children()[0]这是你<panel>在这种情况下, 已经转化 的角度。 clone.children()已经成为:
$compile(clone.children()[0])(scope)
clone.children()[0]
<panel>
clone.children()
<div ng-transclude="">fsafsafasdf</div>
(面板元素已被 移除和更换 )。
与您使用编译普通div相同ng-transclude。当您使用编译普通div时ng-transclude,angular会抛出异常,如文档中所述:
ng-transclude
当您忘记设置transclude:true在某些指令定义中,然后在指令的模板中使用ngTransclude时,通常会发生此错误。
演示(检查控制台以查看输出)
即使您设置replace:false为保留<panel>,有时您也会看到转换后的元素,如下所示:
replace:false
<panel class="ng-scope"><div ng-transclude=""><div ng-transclude="" class="ng-scope"><div ng-transclude="" class="ng- scope">fsafsafasdf</div></div></div></panel>
这也是有问题的,因为ng-transclude重复
演示
为避免 与角度编译过程 发生 冲突 ,建议您将的内部html设置<panel1>为template或templateUrl属性
<panel1>
您的HTML:
<div data-ng-app="app"> <panel1> </panel1> </div>
您的JS:
app.directive('panel1', function ($compile) { return { restrict: "E", template:"<panel><input type='text' ng-model='firstName'>{{firstName}}</panel>", } });
如您所见,此代码更简洁,因为我们不需要手动处理元素。
更新 了不使用template或templateUrl即可动态添加元素的解决方案:
app.directive('panel1', function ($compile) { return { restrict: "E", template:"<div></div>", link : function(scope,element){ var html = "<panel><input type='text' ng-model='firstName'>{{firstName}}</panel>"; element.append(html); $compile(element.contents())(scope); } } });
如果要将其放在html页面上,请确保不要再次编译它:
如果您需要为每个孩子添加一个div。只需使用开箱即用ng-transclude。
app.directive('panel1', function ($compile) { return { restrict: "E", replace:true, transclude: true, template:"<div><div ng-transclude></div></div>" //you could adjust your template to add more nesting divs or remove } });
演示(您可能需要根据需要调整模板,删除div或添加更多div)
根据OP更新的问题的解决方案:
app.directive('panel1', function ($compile) { return { restrict: "E", replace:true, transclude: true, template:"<div ng-transclude></div>", link: function (scope, elem, attrs) { elem.children().wrap("<div>"); //Don't need to use compile here. //Just wrap the children in a div, you could adjust this logic to add class to div depending on your children } } });