当前位置: 首页 > 面试题库 >

在模板中非法使用ngTransclude指令

韩弘壮
2023-03-14
问题内容

我有两个指令

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="">

我知道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()已经成为:

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

(面板元素已被 移除和更换 )。

与您使用编译普通div相同ng-transclude。当您使用编译普通div时ng-transclude,angular会抛出异常,如文档中所述:

当您忘记设置transclude:true在某些指令定义中,然后在指令的模板中使用ngTransclude时,通常会发生此错误。

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

即使您设置replace:false为保留<panel>,有时您也会看到转换后的元素,如下所示:

<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属性

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

演示



 类似资料:
  • 我正在学习C 17非类型模板参数的新功能。我编写了一个简单的代码片段,如下所示: 据我所知,福 但是,语句使用clang、MSVC 19.27编译,但在GCC 10.2、MSVC 19.25编译时失败。 我的问题是:为什么编译器的行为不同?标准对此有何规定? 链接到编译器资源管理器: 叮当声https://godbolt.org/z/66M695 海湾合作委员会https://godbolt.or

  • 问题内容: 我有一个使用Bootstrap中的标记的表单,如下所示: 这里有很多样板代码,我想简化为一个新的指令-form-input,如下所示: 产生: 我通过一个简单的模板完成了很多工作。 但是,当我开始添加更多高级功能时,我就陷入了困境。 如何在模板中支持默认值? 我想在指令中将“ type”参数公开为可选属性,例如: 但是,如果未指定任何内容,则默认为。我该如何支持? 如何根据属性的存在/

  • 问题内容: 如何使用动态模板创建指令? 这就是我现在所拥有的,它可以正确显示标签。但是,我不确定如何在模板上附加其他HTML。或将2个模板合并为1个。 问题答案: 有类似的需求。做这份工作。(不完全确定这是否是“ THE”方法,仍然可以通过角度进行工作) http://jsbin.com/ebuhuv/7/edit-我的探索测试。 需要注意的一件事(以我的示例为例),我的要求之一是,一旦单击“保存

  • wx:if 预期: any 用法: 根据表达式的值的 truthiness 来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。 注意:如果元素是 <block/>, 注意它并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。 WARNING 当和 wx:if 一起使用时,wx:for 的优先级比 wx:if 更高。详见列表渲染教程 参考: 条件渲染 -

  • 问题内容: 这里有角的菜鸟。我正在创建一个指令以递归显示问题树和子问题树。我正在模板中使用链接,该链接在范围内调用函数。由于某种原因,它不会调用该方法。 这是代码和小提琴http://jsfiddle.net/madhums/n9KNv/ HTML: Javascript: 任何帮助理解这一点将不胜感激。 问题答案: 您遇到范围问题。由于您在指令中使用隔离范围,因此它不再有权访问具有的控制器范围。

  • 问题内容: 我正在使用SVG和angular.js进行大型项目,并且需要对svg指令模板的坚实支持。不幸的是,当angular渲染模板时,它将创建DOM节点,而不是SVG节点。我当前的解决方法是使用jquery.svg自己管理创建和删除节点,但是它受到限制。示例:http://plnkr.co/edit/Xk8wM3?p = preview 我想让指令成为实际的svg元素,而不是一些没有任何实际作