35

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)

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!

Rishabh
  • 3,752
  • 4
  • 47
  • 74
Tony Lâmpada
  • 5,301
  • 6
  • 38
  • 50

7 Answers7

63

remove replace: true on the directive by name '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.

code level observation in angular.js version 1.2.1:

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 .

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 .

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

<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) ?

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 .

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

Harish Kayarohanam
  • 3,886
  • 4
  • 31
  • 55
  • 1
    To keep the 'replace: true' functionality, I opt to wrap the template in div instead. It solved the problem and the resulting html is "cleaner" with 'replace: true'. Thanks for the answer! – Henry Neo Sep 10 '14 at 23:48
  • Thanks to that brief explanation ! You saved me a lot of time ! – Pi Home Server Mar 19 '15 at 21:20
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.

Stanley_A
  • 450
  • 3
  • 10
  • 1
    Thank you I tried all the other solutions in this and other questions but when seeing your problem I remembered that I copied some directives from one folder to another but forgot to delete the old definitions so every directive was defined twice albeit in two different modules. – George Bora Jun 12 '14 at 14:09
  • BAH!... "Ol' cut 'N paste" -- I would upvote this more if I could :-P ... Thanks! – Cody Nov 05 '14 at 00:35
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.

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

Tony Lâmpada
  • 5,301
  • 6
  • 38
  • 50
4

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

ibrabeicker
  • 1,786
  • 2
  • 19
  • 31
  • Seems like even if you declare a directive specific to a module, it get registered in global scope. I wonder is this as design. Looks like a bug for me – fernando Feb 14 '16 at 05:17
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

   <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> 
Illuminati
  • 4,539
  • 2
  • 35
  • 55
1

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).

Community
  • 1
  • 1
blomster
  • 768
  • 2
  • 10
  • 27
0

In my case I had a bootstrap-ui accordion-group directive on an element that had 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">
Julian Mann
  • 6,256
  • 5
  • 31
  • 43