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

comment-based repeater #1646

Closed
wants to merge 11 commits into from
Closed

Conversation

IgorMinar
Copy link
Contributor

  • tests with jQuery currently failing (I'm working on that)
  • IE drops any comments inside of <select> element, so there is no way to get it working there
  • inside of the compile fn of the repeater directive there is no way to tell what the original node looked like, because it has been already replaced with a comment node at that point by transclusion, so I had to tack on a $$originalNodeType property on the linking fn that is built by the transclusion. I'm happy to consider other options if someone suggests some.

@petebacondarwin
Copy link
Member

@IgorMinar - This looks good to me. If you are going to have $$originalNodeType why not go the whole hog and just keep a reference to $$originalNode. It may be useful in the future?

Also, as an aside, have you thought about the idea of a different kind of repeat directive: ng-repeat-children, which would not repeat the element on which is found but instead make copies of the child nodes of said element. This would allow, cases like this, for example:

<ul ng-repeat-children="item in nav">
  <li><a href="{{item.url}}">{{item.title}}</li>
  <li class="separator"></li>
</ul>

@mhevery
Copy link
Contributor

mhevery commented Dec 6, 2012

LGTM.

Can you update ng-repeat documentation and describe the multi-comment as well as IE limitations.

@btford
Copy link
Contributor

btford commented Dec 6, 2012

👍

@IgorMinar
Copy link
Contributor Author

@petebacondarwin

1/ $$originalNodeType vs $$originalNode - I'm just being super cautious about memory leaks. I'd rather not have a potentially big chunk of DOM hanging around. Also $$ prefix means that this stuff is private, don't depend on it. So nobody should be using it. We should find a better way to expose the original node in the future if anybody else will need this info.

2/ ng-repeat-children is not very flexible because it doesn't allow you to have a header or footer (common in tables) that are not repeated.

@petebacondarwin
Copy link
Member

Fair enough about the potential for memory leaks and I appreciate that you don't want to create proliferation of directives that do similar jobs.

One last thought: Comment directives that enclose DOM elements. Should this be baked into the $compile - rather than being hard coded into the ng-repeat directive only - so that other directive developers could make use of it? Then you could easily write comment directives for things like ng-switch and so on - and custom directives like ui-if, for instance.

match;

// comment-based repeater
if (linker.$$originalNodeType === 8) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you not move all this into compile.js and allow comment directives to "contain" DOM elements generically?
This would also resolve the issue of needing to pass down the $$originalNodeType into the link function.

@IgorMinar
Copy link
Contributor Author

@petebacondarwin building this into $compile does make sense. but let's take it one step at a time. I learned quite lot from implementing it as a part of the directive.

how would directives declare that they want the compiler to find the ending comment tag, grab everything in between and use that for transclusion? and do that in a way that would not interfere with regular repeater?

@petebacondarwin
Copy link
Member

@IgorMinar

I might be missing something obvious here...

I guess that you would need to decide a convention for closing comment tags, which generalised what you have done for ng-repeat. I.E. for some directive my-directive you could have

<!-- my-directive -->
DOM NODES
<!-- /my-directive -->

Then when the compiler spots a comment that matches a directive, which has asked for transclusion, it would simply check all the following siblings for a comment that matched the closing comment format. If so then it would pull those nodes into the transclusion function as though they were child nodes of an element.

If your comment directive did not ask for transclusion then it would not look for the closing comment, if it did ask for transclusion and the closing comment is not found then that would be an error.

I am sure there are loads of potential faults with this!!

@IgorMinar
Copy link
Contributor Author

what about handling pseudo-nested comment directives?

<!-- directive: my-directive -->
  <!-- directive: my-directive -->
   some content
  <!-- /my-directive -->
<!-- /my-directive -->

the current repeater doesn't support the case when the "nested" repeater comments are siblings because with repeaters it's very rare to need this. general purpose compiler should however deal with this.

@petebacondarwin
Copy link
Member

Ouch.

On 19 December 2012 13:11, Igor Minar [email protected] wrote:

what about handling pseudo-nested comment directives?

some content

the current repeater doesn't support the case when the "nested" repeater
comments are siblings because with repeaters it's very rare to need this.
general purpose compiler should however deal with this.


Reply to this email directly or view it on GitHubhttps://github.com//pull/1646#issuecomment-11529444.

@petebacondarwin
Copy link
Member

Obviously, this could be done by keeping a depth count but the trouble here
is that you start doing complex analysis of the node structure, which is
supposed to be the job of the browser, which would need to deal with bad
stuff like this:


<!-- directive: my-directive -->
<!-- directive: my-other-directive -->
some content
<!-- /my-directive -->
<!-- /my-other-directive -->

On 19 December 2012 13:20, Peter Bacon Darwin [email protected] wrote:

Ouch.

On 19 December 2012 13:11, Igor Minar [email protected] wrote:

what about handling pseudo-nested comment directives?

some content

the current repeater doesn't support the case when the "nested" repeater
comments are siblings because with repeaters it's very rare to need this.
general purpose compiler should however deal with this.


Reply to this email directly or view it on GitHubhttps://github.com//pull/1646#issuecomment-11529444.

// search for closing comment tag and create the template
while (sibling) {
if (sibling.nodeType == 8 &&
(match = (sibling.textContent || sibling.text).match(NG_REPEAT_END_TAG_REGEXP)) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that sibling.data was a more reliable method for getting the content of the comment - particular with IE8

jqLite('<!-- /ng-repeat -->').data === ' /ng-repeat '

Since you are checking the node type anyway you could simplify the regex and match logic.

@thetrevdev
Copy link

Should this be able to support multiple nested comment repeaters? I realize in the attached scenario I could use divs, but I was trying to support multiple nested repeaters inside of a table where these comments would be required. I thought it might be due to how the browser was generating the dom for the table so I reproduced it outside of a table.

http://plnkr.co/edit/Pw289i

I am a little new to open source, but I am willing to help with just a little direction.

@thetrevdev
Copy link

I made some tweaks and made a pull request to support nested comment based repeaters

@mhevery
Copy link
Contributor

mhevery commented Apr 12, 2013

Too many IE restrictions and not going the direction of the specs. A better way to do it is to have something like this

<div ng-repeat ng-repeat-next</div>
<div> I am part of the repeater</div>

@mhevery mhevery closed this Apr 12, 2013
@al-the-x
Copy link
Contributor

@mhevery can you edit your last comment to make the code readable...? Thanks. :D

@JogoShugh
Copy link

Is this part of 1.0.7 and 1.1.5? When I try this:

http://plnkr.co/edit/pBskLN?p=preview

But, change out script reference to the CDN hosted ones, it doesn't work.

@petebacondarwin
Copy link
Member

@JogoShugh - the comment-based repeater had too many browser specific issues to overcome. We have solved the problem using the ng-repeat-start, ng-repeat-end directives. See http://ci.angularjs.org/view/AngularJS/job/angular.js-angular-master/lastSuccessfulBuild/artifact/build/docs/index.html#!/api/ng.directive:ngRepeat

@worldspawn
Copy link

There are cases where ng-repeat-start|end isn't that helpful.

<ul ng-if="menuNodes !== undefined" >
                        <li ng-repeat-start="node in menuNodes | filter: isVisible" ng-class="{ active : node.active }">
                            <a ng-href="{{node.getParsedPath()}}">{{node.menuTitle || node.title}}</a>
                        </li>
                        <li ng-if="node.active && node.displayChildren" ng-repeat="childNode in node.children | filter: isVisible" ng-class="{ active : childNode.active }"><a ng-href="{{childNode.getParsedPath()}}">{{childNode.menuTitle || childNode.title}}</a></li>
                        <span ng-repeat-end style="display : none"></span>
                    </ul>

Above code has me creating a span element just because. I wanted to repeat the nodes and where a node is active and has childnodes repeat it's child nodes adjacent (not nested) to it.

One thing that would have been gold, at least in my scenario was if I could have put the ng-repeat directive on the ul element and told it to repeat the contents of the element rather than the element (and contents) itself. That would have allowed me to do what I wanted without inserting unwanted element.

@snjoetw
Copy link

snjoetw commented Jan 31, 2014

@worldspawn You can get rid of "" by adding "ng-repeat-end" to your 2nd

  • @worldspawn
    Copy link

    Hmm that seems to work. Thanks.

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

    Successfully merging this pull request may close these issues.

    9 participants