如何在AngularJS中的同一个元素上嵌套两个指令?

时间:2021-12-25 18:39:27

When I try to nest two directives on the same element I get the following error. Nested "E" directives - Multiple directives [...] asking for new/isolated scope, I want to nest two "E" isolated scoped directives, like in this fiddle. (To actually reproduce the problem, you need to uncomment the <lw> directive)

当我尝试在同一个元素上嵌套两个指令时,我得到以下错误。嵌套的“E”指令——多个指令[…请求新的/隔离的范围,我想嵌套两个“E”隔离的范围指示,就像这把小提琴。(要重现问题,需要取消 指令)

I keep getting this error that I don't understand/know how to fix:

我一直在犯我不明白/不知道如何改正的错误:

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

Wasn't this supposed to work? Thanks!

这不是应该有效吗?谢谢!

7 个解决方案

#1


59  

remove replace: true on the directive by name 'lw' ..

删除替换:在指令上以名称“lw”为真。

That should also solve .

这也能解决问题。

updated fiddle : updated fiddle

更新的小提琴:更新的小提琴

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

Analysis :

分析:

what caused the problem ?

是什么引起了这个问题?

with replace=true for the lw directive what happens is lw has isolate scope, now as replace=true , the replaced element which itself has isolate scope was tried to be replaced there, so what you unknowingly did is you tried to give two scopes for the same element listie.

对于lw指令的替换=true是lw有隔离的范围,现在替换为true,替换的元素本身隔离了作用域,所以你在不知道的情况下尝试给相同的元素listie提供两个作用域。

code level observation in angular.js version 1.2.1:

代码级观察角度。1.2.1 " js版本:

line 5728 : function applyDirectivesToNode is the function that executes compile on directive and here in line 5772 they do this checking if we are trying to assign duplicate scope or in other words same element with two scopes .

第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 is the function which does that check and if in case there is an attempt to assign two scopes to same element it flings that error . So this is how it is designed to be and not a bug .

上面是检查的函数,如果有尝试将两个作用域分配给相同的元素,它会抛出那个错误。这就是它被设计成的样子而不是一个bug。

why replace:true removal solves the problem ?

为什么更换:真正去除解决问题?

by removing replace:true what happened is instead of new directive listie replaced instead of lw , it got appended into it , so it is one isolated scope nested into other, which is absolutely correct and allowed . the nested isolate scope is like

通过删除replace:true所发生的事情是取代新的指令listie而不是lw,它被添加到其中,所以它是一个嵌套在另一个中的隔离范围,这是绝对正确的和允许的。嵌套的隔离范围类似于

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

why wrapping in a div will also work (this is your solution which you considered to be workaround) ?

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

The point to be noted is that the div is not an element with a separate isolate scope .It is just an element. here on replace you are attaching the isolate scope of lw to be attached to a div . (NOTE : The div by itself does not have an isolate scope ), so there is no 2 isolate scopes attached to same element div . so there is no duplication so the assert step passed and it started working .

需要注意的一点是,div不是一个具有独立范围的元素,它只是一个元素。在这里,在replace中,您将把lw的隔离范围附加到一个div。(注意:该div本身没有隔离作用域),因此没有连接到相同元素div的2个隔离作用域。因此没有重复,所以assert步骤通过,并开始工作。

So this is how it is designed to work and definitely its not a bug .

这就是它的工作原理,它绝对不是一个bug。

#2


11  

Just for interest sake, I had the same error. It turned out because I did the old "Cut and Paste" to create a new directive and they had the same name to start with. I forgot to change it which produced this error.

为了利息,我犯了同样的错误。结果是,我做了旧的“剪切和粘贴”来创建一个新的指令,它们以相同的名字开始。我忘记修改了,导致了这个错误。

So for anyone who is as bad as me then here's a possible solution to check.

所以对于像我这样坏的人来说这是一个可能的解决方案。

#3


5  

I managed to fix it by replacing the template code in the wrapper directive. Here's the update fiddle. This is what changed.

我通过替换包装器指令中的模板代码来修复它。这是更新的小提琴。这就是改变。

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

This solves my problem, but it looks like a bug to me. I guess I'll create an issue on Github.

这解决了我的问题,但对我来说,它就像一个bug。我想我会在Github上创建一个问题。

There - https://github.com/angular/angular.js/issues/5428

——https://github.com/angular/angular.js/issues/5428

#4


4  

My problem was because I was including the directive JS file twice

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

#5


3  

I was using Avengers example and after updating to angular 1.4 I started getting this. As it turned out, it had a controller and a directive fighting for scope on the same line

我用了复仇者的例子,在升级到角1.4后我开始得到这个。结果,它有一个控制器和一个指令在同一条线上争夺范围

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

So moved the controller to a separate scope to fix it.

因此,将控制器移动到一个单独的范围来修复它。

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

#6


0  

The accepted response here solved the problem for me.

这里公认的回答为我解决了问题。

Essentially remove the isolated scope from the directive and instead pass the scope property via the directive's link function (in the attributes parameter).

本质上,从指令中删除隔离的范围,而是通过指令的链接函数(在属性参数中)传递范围属性。

#7


0  

In my case I had a bootstrap-ui accordion-group directive on an element that had ng-repeat:

在我的例子中,我有一个bootstrap-ui accordion-group指令,指向一个具有ng-repeat的元素:

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

And solved it by doing this:

通过这样做来解决

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

#1


59  

remove replace: true on the directive by name 'lw' ..

删除替换:在指令上以名称“lw”为真。

That should also solve .

这也能解决问题。

updated fiddle : updated fiddle

更新的小提琴:更新的小提琴

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

Analysis :

分析:

what caused the problem ?

是什么引起了这个问题?

with replace=true for the lw directive what happens is lw has isolate scope, now as replace=true , the replaced element which itself has isolate scope was tried to be replaced there, so what you unknowingly did is you tried to give two scopes for the same element listie.

对于lw指令的替换=true是lw有隔离的范围,现在替换为true,替换的元素本身隔离了作用域,所以你在不知道的情况下尝试给相同的元素listie提供两个作用域。

code level observation in angular.js version 1.2.1:

代码级观察角度。1.2.1 " js版本:

line 5728 : function applyDirectivesToNode is the function that executes compile on directive and here in line 5772 they do this checking if we are trying to assign duplicate scope or in other words same element with two scopes .

第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 is the function which does that check and if in case there is an attempt to assign two scopes to same element it flings that error . So this is how it is designed to be and not a bug .

上面是检查的函数,如果有尝试将两个作用域分配给相同的元素,它会抛出那个错误。这就是它被设计成的样子而不是一个bug。

why replace:true removal solves the problem ?

为什么更换:真正去除解决问题?

by removing replace:true what happened is instead of new directive listie replaced instead of lw , it got appended into it , so it is one isolated scope nested into other, which is absolutely correct and allowed . the nested isolate scope is like

通过删除replace:true所发生的事情是取代新的指令listie而不是lw,它被添加到其中,所以它是一个嵌套在另一个中的隔离范围,这是绝对正确的和允许的。嵌套的隔离范围类似于

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

why wrapping in a div will also work (this is your solution which you considered to be workaround) ?

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

The point to be noted is that the div is not an element with a separate isolate scope .It is just an element. here on replace you are attaching the isolate scope of lw to be attached to a div . (NOTE : The div by itself does not have an isolate scope ), so there is no 2 isolate scopes attached to same element div . so there is no duplication so the assert step passed and it started working .

需要注意的一点是,div不是一个具有独立范围的元素,它只是一个元素。在这里,在replace中,您将把lw的隔离范围附加到一个div。(注意:该div本身没有隔离作用域),因此没有连接到相同元素div的2个隔离作用域。因此没有重复,所以assert步骤通过,并开始工作。

So this is how it is designed to work and definitely its not a bug .

这就是它的工作原理,它绝对不是一个bug。

#2


11  

Just for interest sake, I had the same error. It turned out because I did the old "Cut and Paste" to create a new directive and they had the same name to start with. I forgot to change it which produced this error.

为了利息,我犯了同样的错误。结果是,我做了旧的“剪切和粘贴”来创建一个新的指令,它们以相同的名字开始。我忘记修改了,导致了这个错误。

So for anyone who is as bad as me then here's a possible solution to check.

所以对于像我这样坏的人来说这是一个可能的解决方案。

#3


5  

I managed to fix it by replacing the template code in the wrapper directive. Here's the update fiddle. This is what changed.

我通过替换包装器指令中的模板代码来修复它。这是更新的小提琴。这就是改变。

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

This solves my problem, but it looks like a bug to me. I guess I'll create an issue on Github.

这解决了我的问题,但对我来说,它就像一个bug。我想我会在Github上创建一个问题。

There - https://github.com/angular/angular.js/issues/5428

——https://github.com/angular/angular.js/issues/5428

#4


4  

My problem was because I was including the directive JS file twice

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

#5


3  

I was using Avengers example and after updating to angular 1.4 I started getting this. As it turned out, it had a controller and a directive fighting for scope on the same line

我用了复仇者的例子,在升级到角1.4后我开始得到这个。结果,它有一个控制器和一个指令在同一条线上争夺范围

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

So moved the controller to a separate scope to fix it.

因此,将控制器移动到一个单独的范围来修复它。

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

#6


0  

The accepted response here solved the problem for me.

这里公认的回答为我解决了问题。

Essentially remove the isolated scope from the directive and instead pass the scope property via the directive's link function (in the attributes parameter).

本质上,从指令中删除隔离的范围,而是通过指令的链接函数(在属性参数中)传递范围属性。

#7


0  

In my case I had a bootstrap-ui accordion-group directive on an element that had ng-repeat:

在我的例子中,我有一个bootstrap-ui accordion-group指令,指向一个具有ng-repeat的元素:

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

And solved it by doing this:

通过这样做来解决

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