-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Transclude type multi-element, use this for ng-repeat #2531
Conversation
feat(ng-repeat): Make ng-repeat of transclude type multi-element Add a new transclude type multi-element to be able to handle transclusion that includes more elements than the one where the directive is present Make the changes to ngRepeat so it is of transclude type multi-element Closes angular#1891
Remove a tab from the code
Fix an issue with nested multi-element directives that are siblings at the DOM level
I skimmed through this PR and it looks really good! Some feedback:
keep up the good work! |
@@ -418,9 +419,12 @@ function $CompileProvider($provide) { | |||
* rootElement must be set the jqLite collection of the compile root. This is | |||
* needed so that the jqLite collection items can be replaced with widgets. | |||
* @param {number=} max directive priority | |||
* @param {boolean=} if the max priority should only apply to the first element in the list. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo:
@param {boolean=} if the max ...
should be:
@param {boolean=} limitMaxPriorityToFirstElement if the max ...
Also, I think that it would be useful to explain why this parameter has been added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will make the change to @param
but I am not sure about adding the full explanation on why this new parameter was added. Just for completeness, it would be something like this
When extracting a multi-element block, we need to remove the block and compile it to create the linking function for the entire block. Now, before the patch, then calling this compile function, sometimes we call it with one element and a maxPriotity (this was for transclusion = 'element') or with multiple elements and no maxPriotity. With multi-element transclusion, we need to handle another case, this is to get multiple elements but there should be a limit on the priority but just to the first element.
Note: In a strict sense it should be possible to remove this parameter and make the assumption that the maxPriority only applies to the first element when nodeList has multiple elements, but I think it makes clearer that, even when there is some redundancy
I am a bit worried about the animation stuff. I think the ng-repeat directive as it stands doesn't take into account that the template now may contain multiple elements, which all need to be animated. |
Avoid cloning elements during a multi-element transclude Put only one comment that will be sent to the linking function and remove all the placeholde elements Cleanup the containsAttr method with an implementation from @petebacondarwin Fixes on the unit tests to follow angular#2492 Document the transclude type 'multi-element' at the docs Fix a typo on the method compileNodes Move the important unit tests from ngRepeatStartSpec to ngRepeatSpec Add more tests at compile for the new multi-element transclude
Merge from trunk to get the modification on ngRepat for #2492 |
I think as it stands now it would allow weird things like this:
This of course is non-sense. I think the grouping should not be associated with any one directive so what we really want is this
Also the grouping should make it clear that any directives define on the ng-with-next can only be accessed after transclusion. Here the ng-with-next is pseudo directive for the compiler not a real directives. Also I don't think that directives should allow for special multi-transclude. There is only one transclude, in some cases it just happens to have multiple elements. So it is not something which needs to be specified explicitly. What do you guys think of this? |
@mhevery It should not allow <div a a-start></div>
<div b b-start></div>
<div a-end></div>
<div b-end></div> as the compilation process will do the following:
<div a a-start></div>
<div b b-start></div>
<div a-end></div>
The reason on why a new transclude type |
Fix for the extended `remove` function that is used during `multi-element` transclusion to also remove the element from its parent when there is one
@mhevery - it would be beautiful if we could make it so that any directive that transcludes can support multiple top level nodes in it transclusion (something like ng-transclude-start, ng-transclude-end) but as @lgalfaso points out this would require lots of directives to change the way that they handle transclusion - i.e. they would need to know that they need to move or remove multiple elements. |
Even when I think that the new transclude type Keep in mind that the templates are not valid, but are just examples of issues Nested repeats that start at the same element <dl>
<dt ng-repeat="group in groups" ng-repeat-start ng-repeat="item in group">{{item}}</dt>
<dd ng-repeat-end>{{group}}</dd>
</dl> Nested repeats that end at the same element <dl>
<dt ng-repeat="group in groups" ng-repeat-start>{{group}}</dt>
<dd ng-repeat="item in group" ng-repeat-start>{{item.id}}</dd>
<dd ng-repeat-end ng-repeat-end>{{item.name}}</dd>
</dl> Now, in a strict sense, I think this is a limitation on ng-repeat (and for sure, something that should not be part of this PR) If this PR moves forward, will look into how to solve these issues |
@lgalfaso - multiple ng-repeats on a single element are not very reliable even now, so I wouldn't worry about this. |
|
@lgalfaso - this will need to be rebased onto master since the animation css class names have changed. |
Currently failing to build: http://ci.angularjs.org/job/angular.js-pete/153/console |
Getting better - after a few tweaks - but of course Internet Explorer is complaining: http://ci.angularjs.org/job/angular.js-pete/154/console |
style($compile): clarify argument name Merge branch 'master' into ng-repeat-start Conflicts: test/ng/directive/ngRepeatSpec.js
@petebacondarwin I do not have IE8 to test this, would it be possible to know if 6861142 passed at IE8? |
Here you go... |
Ok, let me look for an IE8 box image and figure this out |
Fix for [].splice on IE8 that has the second argument as mandatory Fix for arrays on IE8 that adds an extra element on trailing comma
@petebacondarwin 0fae109 fixes the IE8 issues |
transcludeContent.push(cursor); | ||
cursor = cursor.nextSibling; | ||
} while(count > 0 && cursor); | ||
if (count > 0) throw Error('Unmatched ' + transcludeStart + '.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should be throw new Error...
without new
the stack trace will contain an extra frame which looks confusing.
Add a `new` when throwing an error
Thanks @IgorMinar added the |
This PR is now superseded by this one: #2783 Very good idea, I have built upon your idea and implemented a more generic version. Closing |
The patch adds a new transclude type multi-element to be able to handle transclusions that include more elements that the one with the directive. The transclusion type multi-element works in the following way.
When a directive is defined of the type multi-element, then Angular looks for matching attributes named "-start" and -end" and transcludes the entire block. If element where the directive is present does not contain the attribute "-start" then the transclusion works just as the transclusion type "element"
E.g
The directive ng-repeat is of type multi-element when compiling the template below, the compiler will look for the attribute ng-repeat-start. Given that this is present, it will look for a matching hg-repeat-end attribute. When found the entire block will be used for the linking function