-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Can't access ng-controller inside of a template transluded by a custom directive #1307
Comments
I have encountered the same problem. Having to create divs specifically to put ng-controller kind of downplays the advantages of creating your custom XML for your application. Is there any work-around for this ? Specifically, I found that directives using transclude were the ones most prone to this problem. |
From what I understood in the end, the behavior of transclude is perfectly normal in that it creates its creates a new scope. So does ng-controller, which results in having them each have a distinct scope and thus not be able to interact together. In practice, the custom directive has the last say (iirc), and so its own scope is the one used by the DOM elements that are transcluded, which means that the one the controller was bound to is lost and does not interact with the DOM. There is a solution, which is not a work-around but the intended mecanism (I guess), which is to not use ng-transclude (which creates a scope) and manually transclude your elements directly to the created element. See http://jsfiddle.net/Nu5hn/ Also note that it is possible to use the transclude function in your linker like so ; ...
compile: function (elt, attr, transclude) {
// The link function
return function (scope, elt, attr) {
transclude(scope, function (clone) {
// We append here the transcluded elements bound to the parent scope, which means we don't get in ng-controller's way.
elt.append(clone);
}
}
} In short, to be able to have ng-controller working on your custom transcluding directives, do not use ng-transclude, but transclude manually ! |
I've had the same problem, and this post finally helped me out. However, I first tried the solution provided in the fiddle and, in my case, it didn't work 'cos the controller specified via ng-controller was created after the directives in child elements were linked. Instead, the solution of the post (using the transclude from the compile function) worked correctly, respecting the expected order of instantiation. In any case, this makes creating a custom directive that plays nice with ng-controller quite complex and counterintuitive, a thing that I believe should at least be explained in the doc. |
Running into this issue myself. I believe this issue points to the fact that more work needs to be done to get directives-combinations working predictably. Further it would be helpful if warnings were issued to help developers know something wonky like this issue is happening. It seems unacceptable that nothing in this issue warrants a warning to the end-user. Of course, the ideal case is needing no warning given the root problem is resolved with better API "ergonomics". |
ngController creates a child scope, but the transcluded content inherits from the parent scope rather than the ngController's child scope... is this what you're referring to? I suppose it would be reasonable to solve that... Although I think #4421 (comment) might make more sense --- actually, I am not sure why we aren't throwing with the creation of two new scopes here, which is slightly different from #4421 |
Bump. Same issue here. Debugged for half an hour a custom directive on which I need a controller (every entry of an accordion-group from the Bootstrap<->Angular UI package has it's own), until I found out that controllers won't work on custom directives. This is rather upsetting because it means that I cannot use the accordion (and other UI elements) as-is. |
@caitp can you take a look at this one in the next few days and see if it's fixable? |
vmware guys came across this and pinged me. I asked them to post a better repro so let's wait for that. |
cc: @magizh |
Thanks @IgorMinar Here is a very simple example plunker to refer to and repro the issue. |
I don't think we can really fix this --- it would have a lot of unintentional consequences. We could say "if we see a directive with a new scope, make it the new scope that we use" --- but that would break a ton of other cases. We are supposed to be throwing an error if we try to create a new scope and an isolate scope on the same element, so it's not clear why we're not doing that here. |
@IgorMinar this is one of the issues I'm talking about that I don't think we can really fix --- even emitting an error in this case is challenging to do consistently, depending on properties of different directives on the same element. It would be good to get this fixed (because this rightfully should be an error), but it's a maze to make that work properly. |
ok. I understand now. The problem really is that we are creating two new scopes per element, which is something we historically tried to prohibit and this is one of the cases where our error detection failed to notice it and report it to the developer. If we could improve the error detection that would be great (but as @caitp suggest it's not a trivial change), but I'm going to close this issue since we will never support this use case. |
As far as work-arounds go: Is there at least a way to piggyback, or modify the controller or link function on existing directives (that you don't want to temper with)? |
I need to use a Controller scope inside a custom directive which doesn't work:
http://plnkr.co/edit/30MrSh?p=preview
However, putting it outside of the custom directive worked:
http://plnkr.co/edit/g7nQ2x?p=preview
Related: https://groups.google.com/forum/?fromgroups=#!topic/angular/_cjJaJPWzww
The text was updated successfully, but these errors were encountered: