在模板中非法使用ngTransclude指令 [英] Illegal use of ngTransclude directive in the template

查看:1554
本文介绍了在模板中非法使用ngTransclude指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个指令

  app.directive('PANEL1',函数($编译){
    返回{
        限制:E,
        transclude:元素,
        编译:功能(元素,属性,连接器){
            返回功能(范围,元素,属性){
                变种父= element.parent();
                连接器(范围,功能(克隆){
                    。父prePEND($编译(clone.children()[0])(范围)); //引起错误。
                  //父prePEND(克隆); //这一行删除错误,但我想要访问的孩子在我的真正的应用程序。
                });
            };
        }
    }
});app.directive('板',函数($编译){
    返回{
        限制:E,
        更换:真实,
        transclude:真实,
        模板:< D​​IV NG-transclude>< / DIV>中,
        链接:功能(范围,ELEM,ATTRS){
        }
    }
});

这是我的看法:

 <&PANEL1 GT;
    <面板>
        <输入类型=文本NG模型=名字/>
    < /面板>
< / PANEL1>

错误:在模板:[ngTransclude孤儿]非法使用ngTransclude指令!需要找到transclusion没有父指令。元素:< D​​IV CLASS =NG-范围NG-transclude =>

我知道PANEL1不是一个实际的指令。但在我的实际应用中我遇到这个问题了。

我看<一些解释href=\"http://docs.angularjs.org/error/ngTransclude:orphan\">http://docs.angularjs.org/error/ngTransclude:orphan.但不知道为什么,我在这里有这个错误以及如何解决它。

修改
我创建了一个的jsfiddle 页面。谢谢你在前进。

修改

 我在我的真正的应用程序PANEL1做这样的事情:    &LT;&PANEL1 GT;
    &LT;输入类型=文本&GT;
    &LT;输入类型=文本&GT;
&LT;! - 其他元素或指令 - &GT;
    &LT; / PANEL1&GT;

结果=>

 &LT; D​​IV&GT;
    &LT; D​​IV CLASS =X&GT;&LT;输入类型=文本&GT;&LT; / DIV&GT;
    &LT; D​​IV CLASS =X&GT;&LT;输入类型=文本&GT;&LT; / DIV&GT;
&LT;! - 其他元素或指令裹格 - &GT;
    &LT; / DIV&GT;


解决方案

究其原因是当DOM完成加载,角度会遍历尽管DOM和所有指令转化为它的模板 调用编译和链接功能。

这意味着,当你调用 $编译(clone.children()[0])(范围) clone.children() [0] 这是你的&LT;面板&gt; 在这种情况下的已经转化通过角。
  clone.children()已成为:

&LT; D​​IV NG-transclude =&GT; fsafsafasdf&LT; / DIV&GT;

(面板单元已删除和替换)。

这是一个与你正在编译一个正常的div与 NG-transclude 相同。当你编译 NG-transclude 正常DIV,角抛出异常,因为它在文档中说:


  

通常,当你忘记设置transclude出现此错误:
  真在一些指令定义,然后用ngTransclude在
  指令的模板。


演示(检查控制台查看输出)

甚至当你设置更换:假来留住你的&LT;面板&gt; ,有时你会看到改造这样的元素:

&LT;面板类=NG-范围&GT;&LT; D​​IV NG-transclude =&GT;&LT; D​​IV NG-transclude =级=NG-范围&GT; &LT; D​​IV NG-transclude =级=NG-范围&GT; fsafsafasdf&LT; / DIV&GT;&LT; / DIV&GT;&LT; / DIV&GT;&LT; /面板&gt;

这也是有问题的,因为 NG-transclude 被复制

演示

要避免具有角编译过程中发生冲突,我建议设置&LT的内部HTML; PANEL1&GT; 作为模板或templateUrl财产

您的HTML:

 &LT; D​​IV数据-NG-应用=应用程序&GT;
        &LT;&PANEL1 GT;        &LT; / PANEL1&GT;
    &LT; / DIV&GT;

您JS:

  app.directive('PANEL1',函数($编译){
            返回{
                限制:E,
                模板:&LT;面板&gt;&LT;输入类型='文本'NG模型='的firstName'&GT;的{{Firs​​tName}}&LT; /面板&gt;,            }
        });

如你所见,这code是清洁的,因为我们并不需要处理手动transcluding的元素。

演示

更新一个解决方案中添加动态元素,而无需使用模板或templateUrl:

  app.directive('PANEL1',函数($编译){
            返回{
                限制:E,
                模板:&LT; D​​IV&GT;&LT; / DIV&gt;中,
                链接:功能(范围,元素){
                    VAR HTML =&LT;面板&gt;&LT;输入类型='文本'NG-模式='的firstName'&GT;的{{Firs​​tName}}&LT; /面板&gt;,
                    element.append(HTML);
                    $编译(element.contents())(范围);
                }
            }
        });

演示

如果你想要把它的HTML页面上,确保不要再编译:

演示

如果你需要为每个孩子每增加一个div。只需使用外箱 NG-transclude

  app.directive('PANEL1',函数($编译){
            返回{
                限制:E,
                更换:真实,
                transclude:真实,
                模板:&LT; D​​IV&GT;&LT; D​​IV NG-transclude&GT;&LT; / DIV&GT;&LT; / DIV&gt;中//你可以调整你的模板,以增加更多的div的嵌套或删除
            }
        });

演示(你可能需要调整模板,以您的需求,删除分区或添加更多的div)

基于OP的更新问题解决方法:

  app.directive('PANEL1',函数($编译){
            返回{
                限制:E,
                更换:真实,
                transclude:真实,
                模板:&LT; D​​IV NG-transclude&GT;&LT; / DIV&gt;中,
                链接:功能(范围,ELEM,ATTRS){
                    。elem.children()换行(&LT; D​​IV&gt;中); //不需要使用编译这里。
                   //只是包装孩子们在一个div,你可以调整这个逻辑添加类取决于你的孩子的div
                }
            }
        });

演示

I have two directive

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) {
        }
    }
});

And this is my view :

<panel1>
    <panel>
        <input type="text" ng-model="firstName" />
    </panel>
</panel1>

Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: <div class="ng-scope" ng-transclude="">

I know that panel1 is not a practical directive. But in my real application i encounter this issue too.

I see some explanation on http://docs.angularjs.org/error/ngTransclude:orphan. But in don't know why i have this error here and how to resolve it.

EDIT I have created a jsfiddle page. Thank you in advance.

EDIT

I my real app panel1 does something like this:

    <panel1>
    <input type="text>
    <input type="text>
<!--other elements or directive-->
    </panel1>

result =>

    <div>
    <div class="x"><input type="text></div>
    <div class="x"><input type="text></div>
<!--other elements or directive wrapped in div -->
    </div>

解决方案

The reason is when the DOM is finished loading, angular will traverse though the DOM and transform all directives into its template before calling the compile and link function.

It means that when you call $compile(clone.children()[0])(scope), the clone.children()[0] which is your <panel> in this case is already transformed by angular. clone.children() already becomes:

<div ng-transclude="">fsafsafasdf</div>

(the panel element has been removed and replaced).

It's the same with you're compiling a normal div with ng-transclude. When you compile a normal div with ng-transclude, angular throws exception as it says in the docs:

This error often occurs when you have forgotten to set transclude: true in some directive definition, and then used ngTransclude in the directive's template.

DEMO (check console to see output)

Even when you set replace:false to retain your <panel>, sometimes you will see the transformed element like this:

<panel class="ng-scope"><div ng-transclude=""><div ng-transclude="" class="ng-scope"><div ng-transclude="" class="ng-scope">fsafsafasdf</div></div></div></panel>

which is also problematic because the ng-transclude is duplicated

DEMO

To avoid conflicting with angular compilation process, I recommend setting the inner html of <panel1> as template or templateUrl property

Your HTML:

<div data-ng-app="app">
        <panel1>

        </panel1>
    </div>

Your JS:

app.directive('panel1', function ($compile) {
            return {
                restrict: "E",
                template:"<panel><input type='text' ng-model='firstName'>{{firstName}}</panel>",

            }
        });

As you can see, this code is cleaner as we don't need to deal with transcluding the element manually.

DEMO

Updated with a solution to add elements dynamically without using template or 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);
                }
            }
        });

DEMO

If you want to put it on html page, ensure do not compile it again:

DEMO

If you need to add a div per each children. Just use the out-of the box 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 
            }
        });

DEMO (you may need to adjust the template to your needs, remove div or add more divs)

Solution based on OP's updated question:

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
                }
            }
        });

DEMO

这篇关于在模板中非法使用ngTransclude指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆