-
Notifications
You must be signed in to change notification settings - Fork 27.5k
angular 1.2.18: ng-repeat problem with transclude #7874
Comments
oh lawdy. @petebacondarwin want to do another one of these? this is really the "don't create a sibling scope with ng-transclude" thing again, it's just that it worked before for this case due to brokenness |
(maybe) related: #7842 |
Sadly, this is not how I ran into this a few times in the past and had a long debate with Misko about it. The content that is transcluded is by definition bound to the scope of the place where the directive is instantiated; not to the scope of the directive's template. Previously this may have worked as we were actually binding the transclusion to the wrong scope in some cases that involved nested transclusion scenarios. So actually you don't really need to use transclusion here as what you really trying to do is simply inject the inner HTML into your own template. You can do this in the compile function like this: http://plnkr.co/edit/j3NwMGxkVRM6QMhmydQC?p=preview
|
Another example of this (I believe): Index.html:
index.js:
Worked with Angular 1.2.1, but not with 1.2.18; The innocent developer could only expect the code above to work. This doc says:
While the ngTransclude documentation says:
How does this differ from @petebacondarwin definition:
I really don't understand why transclusion isn't the right solution here. If anything I would expect the reasonable solution to involve injecting the template scope to the transclusion function. |
The difference is that transcluded content is bound to the "outside", i.e. the scope of place where the |
I guess you could create your own directive which does indeed inject the template scope into the transclusion function... |
What you are saying makes perfect sense - but that is only if you understand the depths of Angular. My point is that the example above should somehow work without too much extra work. Seems to me very reasonable, and highly practical for the transclusion function to be able to access to the template (or the 'inside') scope somehow. I can think of many cases why this will be needed. The very same issue is explained in this blog. My reckoning that more and more people will complain about how things are at the moment (there's already a multitude of related issues on Github as a result of this behaviour). |
And thanks very much for the code. I'm replicating it here for the benefit of others:
|
:-) I agree that transclusion is not an easy topic to understand without a lot of head scratching and keyboard banging. |
Personally, I feel the current documentation, at least on this pivotal page, is fairly explicit and clear:
(and everything that follows illustrates this further). I would consider adding perhaps the directive you have provided to the framework, possibly branding it 'ng-transclude-internal'? I know of at least one more person who had a go at this, with the directive called 'transcope'. |
I have tried solution, but I faced with other problem, why into ng-repeat parent scope is not scope of directive |
@luboid the reason that doesn't work in your plunker is because your directive has an isolate scope, and the modified compiled DOM (don't do this, by the way, this is a silly way to solve this problem) will use a sibling of the isolate scope's parent. I'll add an example of a proper way to make that work how you expect. (But, this is still a pretty awful design in general, there's no good reason to do this) |
Actually, come to think of it, with ng-repeat or other element transclusion directives you can't really fix this. So yeah, that won't work ever since about version 1.2.0 |
@petebacondarwin A really newbie question here. Why use
|
It is generally best to create a new scope if you are going to compile some new elements, since you are not sure if the original directive is collocated with some complex directive that also wants to create scope, etc. But you might be able to get away with it here... |
Thanks for help, |
@Izhaki @petebacondarwin Thanks so much for that include directive. Just finally updated from 1.2.16 to 1.2.20 and it took be a bit to see why my app started breaking so hard. I thought transclusion was a pretty simple concept before I found this thread. Nope. |
Thanks to everyone who's been helping to clear this up. Updating to 1.2.21 broke much of our interface because of the issues described here, and now we're on the right track. @caitp @petebacondarwin: It would be very helpful if we could get two additional pieces of information:
|
https://github.com/angular/angular.js/blob/master/CHANGELOG.md#120-timely-delivery-2013-11-08 I was referring to these in particular
But, I can't really remember what I was even talking about anymore, who knows ヽ༼ຈل͜ຈ༽ノ |
In the changelog, there are only two kinds of messages: changes and breaking changes. This wasn't considered a breaking change, but rather a bugfix. It was difficult to predict that many people used this this behavior. But it should probably go into the migration docs (which need some love) |
Sho' 'nuff. Those are the ones. I was looking for changes related to transclusion, but this is clearly a change in isolate scope that is incidental to transclusion. Thanks! |
As Angular-1.2.18 fixed a bug with transclude scoping, we need to use a custom transclude directive (which we call inject). See upstream issue and especially the following: angular/angular.js#7874 (comment)
This change broke our code as well. It would be nice to have some easy declarative way of accessing those directive's Here is the demo that works in 1.2.17 and broken since 1.2.18 |
@caitp, nice one, thanks. We have a lot of solutions! |
For those watching this issue, I've created an 'improved' ng-transclude directive, the attribute value of which defines the internal scope sought after and can be one of 3:
Example usage:
Full exampleSee this plunk for an example of all. The output looks like so: Source
|
@Izhaki - FWIW, +10. Doesn't break the current conventions, but adds a clean, declarative way of voluntarily accessing a common use-case. Thanks! |
👍 for @Izhaki's solution. I will be using this as is but would feel much more comfortable if it were included in angular. |
+1 |
@Izhaki +1, great example! |
Thanks for the custom transclude directive. I ended up just making a separate custom transclude instead of overriding the default. There are a couple function calls in your patch that I'm not sure where they come from. minErr() and startingTag() |
@dehru - these functions are internal to AngularJS. |
@Izhaki thanks a lot! I have forked your plunk which repeats the transcluded content, if anyone interested. |
@Izhaki Very nice. |
Izhaki, this is awesome. I heart you. |
@Izhaki This is a very nice solution to the problem of child scopes. Thanks. I am confused though, and was wondering if you could explain, how the inheritance of the $transclude function carries from the outer directive to the ngTransclude directive? It is not explicitly stated anywhere official that I could find, but I assumed that |
I fought with this for days as well as the fact that transclude inserts the transcluded elements within the transclude placeholder instead of replacing it with them. I have found that ng-transclude-replace handles both issues! http://gogoout.github.io/angular-directives-utils/#/api/ng-directives-utils.transcludeReplace I don't need to propagate the ng-repeat directive down into the repeated directive itself or anything of the sort! All appears to be working, including all validations/bindings. Here is a snippet of my code:
|
@abobwhite Thanks for mentioning ng-transclude-replace , great fix. |
-- Created new directive for responsive carousel -- Created new directive for fixing scope issue(angular/angular.js#7874 (comment)) with ng-transclude
I've recently run into this problem. While @Izhaki's worked for me, I'm curious if a best practice has emerged in the time since this discussion. In particular, has there been any interest in making |
@telekid - We don't have plans to include this feature in core right now. |
I see there are solutions and work arounds, but it would be very convenient if there was a way to access the directive's inside scope. |
I would like to point out that I updated the transclude mod that @Izhaki created to angular 1.5 so that it works with multi-slot transclusion. |
What I ended up doing was just using So I have something like:
|
Hi @moneytree-doug : I use this solution you provided, but I find the scope of transclude-this is still the directive scope, not the child of new scope which is generated by ng-repeat. Can you give me some suggestions? |
@szetin Could you put up a jsfiddle showing me what you expect vs what is happening? |
When pass to a directive by ng-transclude, html content with reference {{item}} that you want to repeat (through ng-repeat="item in collection" implemented in the directive) does not work with version 1.2.18
http://embed.plnkr.co/EvzF25sPD3uZLQivDFqy/preview
The text was updated successfully, but these errors were encountered: