Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Stamped copies from transcluded directives don't inherit controllers in all cases #2533

Closed
colinkahn opened this issue Apr 28, 2013 · 7 comments

Comments

@colinkahn
Copy link
Contributor

jsFiddle: http://jsfiddle.net/colinkahn/PL9gD/

The ngRepeat happens at priority: 1000, while the outerDirective happens before at a priority: 2000. You can see that the controller from the outerDirective is lost when the ngRepeat stamps out the new elements from the template. If the outerDirective had a priority that was lower than the ngRepeat, then the controller is added to stamped out elements and then (as expected) available to the innerDirective.

What this also means (but isn't shown here for brevity) is that if outerDirective essentially did what ngRepeat did (was transcluded, stamped out copies from an array), and had a controller, its controller would not be inherited to the innerDirective.

@IgorMinar
Copy link
Contributor

this looks real, thanks for reporting!

@petebacondarwin can you have a look please?

@petebacondarwin
Copy link
Member

Yep. I saw this bug a few months back (#1805) but never got round to submitting a fix.

@mhevery
Copy link
Contributor

mhevery commented Apr 29, 2013

I would like to know what the actual issue is as this example is contrived. A simple fix is here: http://jsfiddle.net/PL9gD/7/

What you are asking for is to create a controller on an element which is transcluded. But in the case of the repeater if you have no items in the repeater where exactly should the outerController be?

There seems to be an issue here, but the attached example does not demonstrate the actual need. Could you collaborate more on what you were doing so that we can better evaluate the issue?

@mhevery mhevery closed this as completed Apr 29, 2013
@mhevery mhevery reopened this Apr 29, 2013
@colinkahn
Copy link
Contributor Author

@mhevery in some ways this is to solve an un-intuitive aspect of using directives that require controllers, and as a specific example, in cases where you could not easily (and arbitrarily) wrap directives, specifically with tables, your workaround won't always be possible.

From my understanding, in the case of there being a zero element repeater, the controller would still exist on the "comment" version of the transcluded directive. I would have to delve into the compiler code to see whether the timing of all of this makes that true (which I don't have time to do right now), but since by the time you get to the linking function your $element already has its controller on its data i would assume that instantiating the controller for a directive is done post-compile, pre-linking.

@colinkahn
Copy link
Contributor Author

To clarify the point above about the controller being on the "comment" version of the $element, this is under the assumption that the cloned controllers will share a "group" controller. The other option would be having a new version of the controller being instantiated with each clone... if the later was the case then i'm not sure what additional changes would need to be made since it would seem that adding a new controller to each cloned element should happen in the returned "linker" function when it calls its callback creating the new clone.

@petebacondarwin
Copy link
Member

@mhevery - the problem, as I see it, is that whenever you transclude an element that has had a directive controller attached to it before the transclusion, this directive controller is "lost", since the controller gets attached to the comment, which is created by the compiler, rather than to the transcluded element.

What this means in practice is that certain reasonable scenarios, such as a suite of directives that rely on a parent directive controller and transclusion stop working. A concrete example came from when I was trying to rewrite an accordion directive to use templates and transclusion. We wanted this structure:

<accordion>
  <accordion-group>...</accordion-group>
</accordion>

where the accordion directive created a controller that was used by the accordionGroup directives. This works fine until you try to replace the accordion element with a template and use ng-transclude inside the template. Which is basically what I have shown, simplified, in this plunker: http://plnkr.co/edit/PfJ6v6Pggs5beaxq0o2E

@IgorMinar
Copy link
Contributor

this was fixed by 45f9f62

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants