Should directive's isolation scopes affect each other?

1,065 views
Skip to first unread message

ni...@bitcasa.com

unread,
Jun 19, 2012, 7:13:03 PM6/19/12
to ang...@googlegroups.com
When 1.0 came out, I finally switched from doing $scope.$watch(attributes.myAttribute) to using the new isolation scope syntax.  Unfortunately, this broke things in ways I wasn't expecting.  Two directives on the same element can isolate each other's scopes!

I found this very strange.  I thought directives were supposed to live in their own little worlds.  I thought that was the whole point of the isolation scope.  But apparently using an isolation scope in one directive will also isolate the scope of all other directives on the same element.  I filed a bug about it, but it was promptly closed.  Apparently it is supposed to work this way.

So I ask, is this what we really want?    I think it hinders reusability if directives can affect each other like this, leaking implementation information.  It also limits the usefulness of the new isolation scope syntax, since using $watch or $eval does not cause these problems, and that's what I went back to doing when I discovered this.

What should I learn from this?  That you shouldn't put two directives on the same element if they use isolation scopes?  If you do, which one wins?  What order are they applied in?

What is the isolation scope for, anyway?  I guess it's really supposed to isolate the scope of the whole tree under that element?  I thought it was just supposed to create a scope for the purposes of one directive.  I'd like to see an option for this.

Igor Minar

unread,
Jun 19, 2012, 7:24:41 PM6/19/12
to ang...@googlegroups.com
Allowing multiple scopes per element is something that we considered, but we feared that this would result in a lot of confusion and would also make debugging much harder that's why we decided to limit this to one scope per element.

The isolate scope is supposed to allow you to do encapsulation which ultimately allows component reusability. Having two directives ask for an isolate scope doesn't really make much sense, because the isolate scope is useful mainly in situations in which a component/directive is backed by a template with bindings. And you can't have the same element backed with two or more templates.

My suggestion is to use isolate scopes when you are creating reusable components that are backed by a template. If you want to compose multiple directives together, you should design them in a way that make one directive the main one (with the template) and the other directives are just helper directives (sort of like traits or mixins in some programming languages).

/i

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/Mk4EooPPTjgJ.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

ni...@bitcasa.com

unread,
Jun 19, 2012, 7:27:06 PM6/19/12
to ang...@googlegroups.com
Okay, I think I understand the reasoning here.  The isolate scope is to isolate a particular part of the dom from the rest of the dom.  I guess this could be useful for reusable components whose template portion is still inside the parent template.  This could be very unintuitive though, as users may expect to be able to use values from the parent scope inside the area governed by the isolation scope.  There really is no visible reason you can't do this, until you look at the source code of the directive and see that it uses an isolation scope.  Personally, if I were going to isolate the scope of a template, I would use the template+replace options.  I would expect that a template swapped in by this method would have its scope isolated from the rest of the dom.  I would not expect a template that is part of the parent template would be isolated though.

Anyway, the kind of isolation I wanted was not the sort that isolates a part of my template from the rest of my template.  I wanted a scope that isolates this directive's code from my template.  That means the directive would be reusable, and one could easily throw a lot of different directives at the same element without worrying about them messing each other up, or messing with the application at large.  They would only have access to the data that was passed in through attributes.  I would still want to put other bindings and directives inside that same element.  I can accomplish this using $eval and $watch, but I was really hoping to have a syntax for this that looks like the new isolation scope syntax, because that is a lot prettier and less fiddly.

ni...@bitcasa.com

unread,
Jun 19, 2012, 7:28:56 PM6/19/12
to ang...@googlegroups.com
Yeah, I want to create traits.

I just really want a syntax for this that looks like the isolation scope syntax, so I don't have to set up a bunch of $eval and $watch expressions.

Oliver Batchelor

unread,
Jun 19, 2012, 8:28:40 PM6/19/12
to ang...@googlegroups.com
I had made the same assumption, I thought isolate scopes were so that
I could use several directives and they don't interfere with each
other.

I've been using an isolate scope with the two-way binding like so:
scope { editableHtml : '=' }, but notice that if I use this then I
can't also have an ngHide directive on the same element.

So then I have the choice, take out the isolate scope and use
$watch/$eval (e.g. element.html (scope.$eval(attrs['editableHtml']))
, or wrap it in another element. Neither of which are as nice.


Cheers,
Oliver
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/angular/-/wquBQcOdtOkJ.

Oliver Batchelor

unread,
Jun 19, 2012, 10:08:47 PM6/19/12
to ang...@googlegroups.com
The idea being that you wrap all your data in an object like this?

MyCtrl = function($scope) {
$scope.foo.value = 3;
}

and then you have <div my-directive="foo">, and since it's wrapped in
an object it points at the same value?

Hmm.


On Wed, Jun 20, 2012 at 1:02 PM, Eddie Huang <co...@rocketmail.com> wrote:
> My workaround is <my-directive="stateObject"> and
> then <my-directive="stateObject2">
> https://groups.google.com/d/msg/angular/-/3kreeaSuGWMJ.

Nick R

unread,
Jun 25, 2012, 11:26:58 PM6/25/12
to ang...@googlegroups.com
I was hoping this thread would go somewhere.  The current behavior of isolation scopes really bothers me.  I want a nice syntax like the one isolation scopes have, but for isolating directives from the template entirely.

I don't see this as creating extra scopes in the same way as other scopes in the page.  Directive isolation scopes would not be used in the template unless it was a replacement template defined in the directive itself.  I don't want the directive's isolation scope to affect the outer template at all.  If you want to affect the outer template's scope, you can put a controller on your directive and add things to the scope there.

Oliver Batchelor

unread,
Jun 25, 2012, 11:36:51 PM6/25/12
to ang...@googlegroups.com
Definitely gets my vote too.

Oliver
> --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/angular/-/IMVBGhiPQ6gJ.

Peter Bacon Darwin

unread,
Jun 26, 2012, 1:48:36 AM6/26/12
to ang...@googlegroups.com
Yes, this sounds sensible to me.

wingy

unread,
Aug 16, 2012, 12:42:16 PM8/16/12
to ang...@googlegroups.com, ni...@bitcasa.com
Is this related to your issue?


Wingy

Alex Buchanan

unread,
Nov 6, 2013, 12:45:43 AM11/6/13
to ang...@googlegroups.com
Tossing on a +1 here. This is yet another "gotcha" on a long list when it comes to directives, and left me scratching my head for a bit. In addition, I think there must be tons of use cases for having many, totally unrelated directives on one element, each wanting it's own sandbox to work in.

mike.h...@gmail.com

unread,
Jan 6, 2014, 1:51:32 PM1/6/14
to ang...@googlegroups.com
+1
Reply all
Reply to author
Forward
0 new messages