【问题标题】:How to nest two directives on the same element in AngularJS?如何在AngularJS中的同一个元素上嵌套两个指令?
【发布时间】:2014-01-03 18:37:15
【问题描述】:

当我尝试在同一个元素上嵌套两个指令时,我收到以下错误。 嵌套的“E”指令 - 多个指令 [...] 要求新的/隔离的范围, 我想嵌套两个“E”隔离范围指令,例如this fiddle。 (要真正重现问题,您需要取消注释 指令)

我不断收到这个我不明白/不知道如何解决的错误:

Error: [$compile:multidir] Multiple directives [lw, listie] asking for new/isolated scope on: <listie items="items items">

这不应该有效吗? 谢谢!

【问题讨论】:

    标签: angularjs angularjs-directive


    【解决方案1】:

    删除 replace: true 在指令上的名称 'lw' ..

    这也应该解决。

    更新小提琴:updated fiddle

    app.directive('lw', function(){
        return {
            restrict: 'E',
            scope: {
                items: "="
            },
            template: '<listie items="items"></listie>',
            controller: function($scope) {
            }
        }
    });
    

    分析:

    是什么导致了问题?

    对于 lw 指令使用 replace=true 会发生什么是 lw 具有隔离范围,现在作为 replace=true ,本身具有隔离范围的被替换元素被尝试在那里替换,所以你在不知不觉中所做的是你试图给同一元素列表的两个作用域。

    angular.js 1.2.1 版中的代码级观察:

    第 5728 行:函数 applyDirectivesToNode 是在指令上执行编译的函数,在第 5772 行,他们会检查我们是否尝试分配重复的范围,或者换句话说,具有两个范围的相同元素。

    function assertNoDuplicate(what, previousDirective, directive, element) {
          if (previousDirective) {
            throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
                previousDirective.name, directive.name, what, startingTag(element));
          }
        }
    

    above 是执行该检查的函数,如果尝试将两个范围分配给同一个元素,它会抛出该错误。 所以这就是它的设计方式,而不是错误。

    为什么replace:true删除能解决问题?

    通过删除 replace:true 发生的事情不是新指令 listie 被替换而不是 lw ,它被附加到其中,因此它是一个嵌套在另一个范围内的孤立范围,这是绝对正确和允许的。 嵌套的隔离范围就像

    <lw items="items" class="ng-isolate-scope">
       <div items="items" class="ng-isolate-scope">
            ..........
       </div>
    </lw>
    

    为什么包装在 div 中也可以工作(这是您认为可以解决的解决方案)?

    需要注意的一点是,div不是一个有独立作用域的元素,它只是一个元素。 在此处替换您将附加 lw 的隔离范围以附加到 div 。 (注意: div 本身没有隔离范围),因此没有附加 2 个隔离范围 到相同的元素 div 。 所以没有重复,因此断言步骤通过并开始工作。

    所以这就是它的设计工作方式,绝对不是错误。

    【讨论】:

    • 为了保留“replace: true”功能,我选择将模板包装在 div 中。它解决了这个问题,生成的 html 使用“replace: true”“更干净”。感谢您的回答!
    • 感谢您的简短解释!你为我节省了很多时间!
    【解决方案2】:

    只是为了兴趣,我有同样的错误。原来是因为我做了旧的“剪切和粘贴”来创建一个新指令,并且它们以相同的名称开头。我忘记更改它会产生此错误。

    所以对于像我一样糟糕的人来说,这里有一个可能的解决方案来检查。

    【讨论】:

    • 谢谢我在这个问题和其他问题中尝试了所有其他解决方案,但是当看到您的问题时,我记得我将一些指令从一个文件夹复制到另一个文件夹,但忘记删除旧定义,因此定义了每个指令两次,尽管在两个不同的模块中。
    • 呸!...“Ol' cut 'N paste”——如果可以的话,我会更赞成这个:-P ...谢谢!
    【解决方案3】:

    我设法通过替换包装器指令中的模板代码来修复它。 这是update fiddle。 这就是变化。

    template: '<div><listie items="items"></listie></div>',
    //template: '<listie items="items"></listie>', bug?
    

    这解决了我的问题,但对我来说似乎是一个错误。我想我会在 Github 上创建一个问题。

    那里-https://github.com/angular/angular.js/issues/5428

    【讨论】:

    • 这是解决他的问题最简单的方法,这不是错误
    【解决方案4】:

    我的问题是因为我两次包含指令 JS 文件

    【讨论】:

    • 似乎即使您声明特定于模块的指令,它也会在全局范围内注册。我想知道这是作为设计。对我来说似乎是一个错误
    【解决方案5】:

    我使用的是复仇者联盟的例子,在更新到 angular 1.4 后,我开始得到这个。事实证明,它有一个控制器和一个指令在同一行争夺范围

       <div my-directive ng-controller="myController as vm"></div>
    

    因此将控制器移至单独的范围以修复它。

    <div my-directive >
    <div ng-controller="myController as vm">
    </div>
    </div> 
    

    【讨论】:

      【解决方案6】:

      接受的回复here 为我解决了这个问题。

      基本上从指令中移除隔离作用域,而是通过指令的链接函数(在 attributes 参数中)传递作用域属性。

      【讨论】:

        【解决方案7】:

        在我的例子中,我在一个具有 ng-repeat 的元素上有一个 bootstrap-ui 手风琴组指令:

        <accordion-group is-open="status.open" ng-repeat="receipt in receipts">
        

        并通过这样做解决了它:

        <div ng-repeat="receipt in receipts">
            <accordion-group is-open="status.open">
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-13
          • 2020-10-02
          • 2021-08-07
          相关资源
          最近更新 更多