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

ngRepeat with DL / DD / DT #1891

Closed
leeola opened this issue Jan 26, 2013 · 76 comments
Closed

ngRepeat with DL / DD / DT #1891

leeola opened this issue Jan 26, 2013 · 76 comments

Comments

@leeola
Copy link

leeola commented Jan 26, 2013

Is there any timeframe on when (and how?) ngRepeat is going to handle Definition Lists?

In case you are not familiar with the problem: Currently ngRepeat works with single elements. For most HTML, this works fine.. however for definition lists such as <dl>, this does not work. Why? Because definition lists uses multiple elements to define a single list item.

Now, there are multiple ways around this, but reading here suggests that Angular is going to use comments to support repeating elements.

Any idea on when this feature is going to be implemented? Or if there is a somewhat stable branch that can be merged in to address this? The existing solutions currently are very hacky, against standards, and prone to breaking code in IE/etc.

Thoughts?

edit: By "stable branch that can be merged", i meant a branch that i could fork to run on my site and address this issue until the code is officially merged in. My apologies for the poor wording :)

@maxcan
Copy link

maxcan commented Jan 29, 2013

second this. I've been having this issue for a while.

@petebacondarwin
Copy link
Contributor

@IgorMinar did some work on a comment-based ng-repeat (#1646) but since comments don't play so well on all browsers it is not likely to be merged. Instead they are looking at an alternative solution, probably with either "start and end repeat tags" or "start-repeat and number of elements to repeat label"

@maxcan
Copy link

maxcan commented Jan 29, 2013

How about allowing templates inside pairs like {{ }}

maybe:
{{! ng-repeat = "foo in l"

foo
{{ l }}
!}}

On a related note, i have a similar issue with
Would there be large technical challenges to a second interpolation form
like {{{ }}} that did not escape html characters but also didn't create a
new span?

On Tue, Jan 29, 2013 at 12:38 PM, Pete Bacon Darwin <
[email protected]> wrote:

@IgorMinar https://github.com/IgorMinar did some work on a
comment-based ng-repeat (#1646#1646)
but since comments don't play so well on all browsers it is not likely to
be merged. Instead they are looking at an alternative solution, probably
with either "start and end repeat tags" or "start-repeat and number of
elements to repeat label"


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-12856484.

@zilles
Copy link

zilles commented Feb 8, 2013

I just ran into this issue with a table that wants to generate two 'td' elements per object in an array.

@bowsersenior
Copy link

+1 for adding this feature. Just ran into this same limitation.

@es128
Copy link
Contributor

es128 commented Apr 3, 2013

👍

@jensens
Copy link

jensens commented Apr 19, 2013

Same problem here. I'd love to see something like "ng-repeat-children" repeating only the children but not the current element or a kind of "ng-omit-tag" (which removes the current tag but leaves children in place) to be used together with ng-repeat. This would avoid tons of invalid markup generated to workaround this problem.

@lgalfaso
Copy link
Contributor

Do not fully understand the limitation that is under discussion. Why putting the ng-repeat on the parent element does work? http://jsfiddle.net/JyWdT/13/
Can someone create a fiddle that explains the issue in more detail?

@zilles
Copy link

zilles commented Apr 21, 2013

lgalfaso, Your fiddle creates multiple definition lists each with one definition. The desired output is one definition list with multiple definitions.

Or in my case, I need to create a pair of "td" elements for every item in an array.
Say I have an array,

[{name:dan, age:15}, {name:steve, age:21}]

and I need to output:

<tr><td>dan</td><td>15</td><td>steve</td><td>21</td></tr>

There is no way to accomplish that with angular at this time.

@logicbomb
Copy link

can't you do that by putting the ng-repeat on the tr element?

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

On Sun, Apr 21, 2013 at 2:24 PM, zilles [email protected] wrote:

lgalfaso, Your fiddle creates multiple definition lists each with one
definition. The desired output is one definition list with multiple
definitions.

Or in my case, I need to create a pair of "td" elements for every item in
an array.
Say I have an array,

[{name:dan, age:15}, {name:steve, age:21}]

and I need to output:

dan15steve21

There is no way to accomplish that with angular at this time.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-16716788
.

@logicbomb
Copy link

Oh, I see, disregard my previous comment
On Apr 21, 2013 9:09 AM, "jason turim" [email protected] wrote:

can't you do that by putting the ng-repeat on the tr element?

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

On Sun, Apr 21, 2013 at 2:24 PM, zilles [email protected] wrote:

lgalfaso, Your fiddle creates multiple definition lists each with one
definition. The desired output is one definition list with multiple
definitions.

Or in my case, I need to create a pair of "td" elements for every item in
an array.
Say I have an array,

[{name:dan, age:15}, {name:steve, age:21}]

and I need to output:

dan15steve21

There is no way to accomplish that with angular at this time.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-16716788
.

@stoussaint
Copy link

As I just encounter the dl / dt + dd issue, I confirm that a new ng-repeat-children (or ng-repeat-inner) is a missing mandatory directive.

@choffmeister
Copy link

+1

@lgalfaso
Copy link
Contributor

Proposal for a new directive ng-repeat-inner. If this proposal is ok, then will modify all the guides

@bowsersenior
Copy link

I think it would be better to use the same ng-repeat directive, but allow for that directive to be used on HTML comments, as the original post suggests.

Something like this should then work:

<dl>
  <!-- ng-repeat="(name, definition) in myList" -->
  <dt>{{name}}</dt>
  <dd>{{definition}}</dd>
  <!-- /ng-repeat -->
</dl>

Not sure exactly how the beginning and end of the block to be repeated would be achieved ( <!-- /ng-repeat --> was suggested by @ProLoser), but I think that using HTML comments would be an elegant solution.

@maxcan
Copy link

maxcan commented Apr 23, 2013

Given that minifiers can kill comments and other issues with comments, I
don't think this is great. However, I like the idea of using ng-repeat.
would it be feasible to include an attribute ng-repeat-single-root or
something which when set to true will run the ng-repeat without the root
element? For example:

{i}
{i}

would become:

1
1
2
2
3
3

On Tue, Apr 23, 2013 at 3:54 PM, Mani Tadayon [email protected]:

I think it would be better to use the same ng-repeat directive, but allow
for that directive to be used on HTML comments, as the original post
suggests.

Something like this should then work:

{{name}}
{{definition}}

Not sure exactly how the beginning and end of the block to be repeated
would be achieved (I made up the in my example),
but I think that using HTML comments would be an elegant solution.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-16891970
.

@zilles
Copy link

zilles commented Apr 23, 2013

maxcan, I can see the advantages of "single-root", since you keep the source html valid, but that construct doesn't let you add anything else inside the "dl" tag... A fixed definition for example that you want to include before your loop of dynamic definitions. lgalfaso's solution would handle that.

@lgalfaso
Copy link
Contributor

@maxcan without a big rework or a performance hit, I do not think it is possible to add this property ng-repeat-single-root (well, add it and make it dynamic based on it). The rational is that there is a high chance that a change on this property would cause a recompilation [and nobody likes recompilations]

@ProLoser
Copy link
Contributor

I like @bowsersenior's suggestion, but I'd prefer this as the closing comment: <!-- /ng-repeat -->

@maxcan
Copy link

maxcan commented Apr 24, 2013

That's a shame on the performance hit. Anyway, I strongly endorse
@lgalfaso's solution, assuming you can put the directive in a div and not
just a comment..

On Wed, Apr 24, 2013 at 1:58 PM, Dean Sofer [email protected]:

I like @bowsersenior https://github.com/bowsersenior's suggestion, but
I'd prefer this as the closing comment:


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-16964155
.

@bowsersenior
Copy link

I concur with @ProLoser that <!-- /ng-repeat --> is a better closing tag in the HTML comment approach. One note, angular allows directives to be defined in HTML comments, so I don't think HTML comments can be discarded as a potential solution for this problem. Keep in mind that the core angular developers indicated they planned to use HTML comments to address this issue in this stack overflow question (as pointed out by the original poster):

@maxcan
Copy link

maxcan commented Apr 24, 2013

I dont mind discarding them as long as there is a way to do this without
comments.

On Wed, Apr 24, 2013 at 2:41 PM, Mani Tadayon [email protected]:

I concur with @ProLoser https://github.com/ProLoser that is a better closing tag in the HTML comment approach. One
note, angular allows directives to be defined in HTML comments, so I don't
think HTML comments can be discarded as a potential solution for this
problem. Keep in mind that the core angular developers indicated they
planned to use HTML comments to address this issue in this stack overflow
question (as pointed out by the original poster):


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-16969268
.

@hsdk123
Copy link

hsdk123 commented Apr 25, 2013

+1 to @lgalfaso's ng-repeat-inner. I'd finally like something that just gets this done.

@bsantucci
Copy link

Knockout does this with comments. I'm trying to port something I did with the dl tag in knockout and it seems like that is not possible until this issue is addressed.

lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Apr 25, 2013
Add a new directive ng-repeat-inner that will behave as ng-repeat but
the template that is being repeated is the inner of the element and
not the element itself

Closes angular#1891
@lgalfaso
Copy link
Contributor

This is my opinion, so without the input from @mhevery or @IgorMinar, take this with a grain of salt.
I do see that making ng-repeat work with comments is more flexible, anyhow It does not look natural without a change to $compiler so it can handle a directive of type "between comments". The reason being that it looks odd that a directive needs to take care about nesting and looking outside of the element that it is given to do what it is suppose to

@lgalfaso
Copy link
Contributor

Ok, it looks like the is a real issue with multi-element directives that are at the same level at the DOM. Updated the PR with a fix for this issue

@ghost
Copy link

ghost commented Apr 28, 2013

Fixes such as ng-repeat-inner or ng-repeat-next only solve one of countless situations where binding behaviors to actual DOM nodes will limit you.

Instead of patching every directive individually you can solve this for the entire framework by adding support for virtual nodes which don't render in the actual tree.

The idea of using comments is similar, but it results in unsightly, hard to read code and you still need a way to name that node and close it somehow. Instead of inventing a new comment node syntax, use existing HTML syntax.

Think about it as a concept similar to, say, SASS silent classes:

<div id="myComplexList">
    <ng-virtual ng-repeat="...">
        <a></a>
        <b></b>
        <c></c>
    </ng-virtual>
</div>

Result:

<div id="myComplexList">
    <a></a>
    <b></b>
    <c></c>
    <a></a>
    <b></b>
    <c></c>
    <a></a>
    <b></b>
    <c></c>
    ...
</div>

@leostera
Copy link
Contributor

+1 to the general idea but I'd go for something like ng-repeat-group.

<ng-repeat-group="b in ches">
// group markup to be repeated here
</ng-repeat-group>

@hsdk123
Copy link

hsdk123 commented Apr 28, 2013

I like the idea of a virtual nodes, but I'm against it becoming a general solution for the problem here.

If at all possible, I'd like to limit the creation of any artificial containers. While the container may not show up on the html of the overall result, it would start cluttering up the html code that needs managing.

In many cases, we'll be needing some container to contain what we want to repeat. ex:

<tr>
  <td ng-repeat-start>1</td>
  <td ng-repeat-end>2</td>
</tr>

(the container here being the [tr]s)

using the virtual node solution proposed would turn this into:

<tr>
  <ng-virtual ng-repeat="...">
     <td>1</td>
     <td>2</td>
  </ng-virtual>
</tr>

making a redundant container: even this two line addition makes me feel uncomfortable thinking what it'd be like if the code got longer.

Another issue is that it'll start to make tedious trying to grasp what level of dom the code is currently in.
Here's a bit of code from @es128

<table>
<thead>...</thead>
    <tr ng-repeat-start="(name, definition) in myList">...</tr>
    <tr>...</tr>
    <tr ng-repeat-end>...</tr>
    <tr>...</tr>
    <tfoot>...</tfoot>
</table>

using virtual nodes turns this into:

<table>
<thead>...</thead>
    <ng-virtual ng-repeat="...">
        <tr">...</tr>
        <tr>...</tr>
        <tr>...</tr>
    </ng-virtual>
    <tr>...</tr>
    <tfoot>...</tfoot>
</table>

The repetition of the first 3 trs and the final tr are on the same level, but if I was just to take a quick skim through the code, there's a chance I'll mistake them as different levels, or I'll start finding myself tediously calculating (perhaps incorrectly) what level the code's working on, especially if these things start nesting.

@honzajde
Copy link

Here is a particular version of syntax I like (of kind B):

<ul>
  <li>some static prefix item</li>
  <li ng-repeat-block="(name, definition) in myList">{{ something }}</li>
  <li>{{ something else }}</li>
  <li ng-repeat-block-close>{{ something else }}</li>
  <li>some static postfix item</li>
</ul>

@lgalfaso
Copy link
Contributor

@stanvass your proposal is a variation of what @IgorMinar posted as syntax X, the main issue is that browser support is just not there

@hsdk123
Copy link

hsdk123 commented May 7, 2013

I've just realised that having both a ng-repeat-start and a ng-repeat-end is redundant in the case that you only want to repeat one inner element.

<tr>
  <td ng-repeat-start ng-repeat-end>repeat this</td>
</tr>

It would be nice if we could also have a ng-repeat-single that would prevent this. ex.

<tr>
  <td ng-repeat-single>repeat this</td>
</tr>

@lgalfaso
Copy link
Contributor

lgalfaso commented May 7, 2013

@daegon123 if you want to repeat a single element, just do

<tr>
  <td ng-repeat="...">repeat this</td>
</tr>

No need for ng-repeat-start nor ng-repeat-end

@hsdk123
Copy link

hsdk123 commented May 7, 2013

@lgalfaso Thanks, it seems I've gotten caught up in the proposed syntax so much that I forgot what we already had. Hope we get the ng-repeat-start/end realized soon.

@jensens
Copy link

jensens commented May 7, 2013

I think this issue is not about simply repeating one element. Its more about how to repeat a set of elements without repeating its parent. i.e. <dt>..<dd>... - but there were many other good examples in here.

@zilles
Copy link

zilles commented May 7, 2013

Syntax X is the only one that is well defined once you start nesting repeats. How would you write the following in Syntax A-D:

<template>
  <dl>
    <ng repeat="book in myList">
      <dt ng-repeat="author in book.authors">{{author.name}}</dt>
      <dd>{{book.title}}</dd>
      <dd>{{book.description}}</dd>
    </ng>
  </dl>
</template>

@supercool27
Copy link

It is better suggestion.
Sent from My Blackberry®

-----Original Message-----
From: daegon123 [email protected]
Date: Mon, 06 May 2013 22:57:16
To: angular/[email protected]
Reply-To: "angular/angular.js" [email protected]
Subject: Re: [angular.js] ngRepeat with DL / DD / DT (#1891)

I've just realised that having both a ng-repeat-start and a ng-repeat-end is redundant in the case that you only want to repeat one inner element.

<tr>
  <td ng-repeat-start ng-repeat-end>repeat this</td>
</tr>

It would be nice if we could also have a ng-repeat-single that would prevent this. ex.

<tr>
  <td ng-repeat-single>repeat this</td>
</tr>

Reply to this email directly or view it on GitHub:
#1891 (comment)

@xixixao
Copy link

xixixao commented May 21, 2013

+1, this is a big limitation.

@adityamenon
Copy link

👍 look forward to seeing a solution for this! I'm going with using <li> for now, but would love to refactor that markup when angular comes out with a solution for this =)

@symblify
Copy link

Would #2783 resolve this?

@IgorMinar
Copy link
Contributor

Yes. We have a solution that just landed: e46100f

I'm closing this issue.

@gevgeny
Copy link

gevgeny commented Jun 2, 2013

I got error: <TypeError: Object #<Text> has no method 'hasAttribute'> in this simple example:

<table>
        <tr ng-repeat-start="value in [1,2,3,4]">I get repeated</tr>
        <tr ng-repeat-end>I also get repeated</tr>
    </table>

@kharnt0x
Copy link

kharnt0x commented Jun 3, 2013

Also getting the issue as gevgeny states.
<TypeError: Object # has no method 'hasAttribute'>

<tr>
                <td data-ng-repeat-start="column in selectedItem.Beds" class="text-center">Avail. Beds</td>
                <td data-ng-repeat-end>Extra Bed Spaces</td>
</tr>

@gevgeny
Copy link

gevgeny commented Jun 3, 2013

@kharnt0x see this puul request #2859

@ChrisCinelli
Copy link

How would #2783 resolve this:

{[{h: "1",
   o: [{h: "1.1",
        o: [{h: "1.1.1"},
            {h: "1.1.2"},
            {h: "1.1.3"}]},
       {h: "1.2",
        o: [{h: "1.2.1"},
            {h: "1.2.2"},
            {h: "1.2.3"}]},

....

It need to output something like this:

<h1>1</h1>
<h2>1.1</h2>
<h3>1.1.1</h3>
<h3>1.1.2</h3>
<h3>1.1.3</h3>
<h2>1.2</h2>
<h3>1.2.1</h3>
<h3>1.2.2</h3>
<h3>1.2.3</h3> 

What would it be the syntax?

@gevgeny
Copy link

gevgeny commented Jun 18, 2013

@ChrisCinelli Try use hgroup

<h1>1</h1>
<hgroup>
    <h2>1.1</h2>
        <hgroup>
            <h3>1.1.1</h3>
            <h3>1.1.2</h3>
            <h3>1.1.3</h3>
        <hgroup>
    <h2>1.2</h2>
        <hgroup>
            <h3>1.1.1</h3>
            <h3>1.1.2</h3>
            <h3>1.1.3</h3>
        <hgroup>
<hgroup>

@ChrisCinelli
Copy link

So hgroup seems has been remove from HTML5 ( http://html5doctor.com/the-hgroup-element/ ), beside that, as I was saying the problem is more complex and the header tags were used just for example.
This is clearly a use case that should be allowed and does not break at all the declarative view philosophy of Angular...

@MikeMcElroy
Copy link
Contributor

For the specific output you're looking for, have you considered CSS
Counters?

See:
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Counters
http://css-tricks.com/almanac/properties/c/counter-increment/

On Tue, Jun 18, 2013 at 2:46 PM, Chris Cinelli [email protected]:

So hgroup seems has been remove from HTML5 (
http://html5doctor.com/the-hgroup-element/ ), beside that, as I was
saying the problem is more complex and the header tags were used just for
example.
This is clearly a use case that should be allowed and does not break at
all the declarative view philosophy of Angular...


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-19644594
.

@ChrisCinelli
Copy link

I used the header as an example to make it clear... in reality I have a relatively complex <div> with different structure for each of the levels in the data structure.

The only solution that I found so far is to linearize the data structure in Javascript and use a ng-switch for different levels and it will require me an extra div level.
This solution has overhead (i.e. memory and CPU to linearize the data structure) and the HTML is going to look a lot less clearer than the underscore template that I can use instead...

@MikeMcElroy
Copy link
Contributor

Can you make directives for each level? I'm not sure what kind of
structure you're talking about here, so I'd just be grasping at straws.
But in my experience, ng-switch is hardly ever necessary when you have
access to directives and ng-include, and leads to spaghetti-code templates.

On Tue, Jun 18, 2013 at 4:27 PM, Chris Cinelli [email protected]:

I used the header as an example to make it clear... in reality I have
relatively complex div with different structure for each of the levels in
the data structure.

The only solution that I found so far would be linearize the tree in
Javascript and use a ng-switch for different levels.
This solution has overhead (i.e. memory and CPU to linearize the data
structure) and the HTML is going to look a lot less clearer than the
underscore template that I can be used instead...


Reply to this email directly or view it on GitHubhttps://github.com//issues/1891#issuecomment-19650391
.

@ChrisCinelli
Copy link

This is how it looks like: http://d.pr/i/GSX4
Pretty much short labels (1.x.x x), descriptions, number of checkmarks etc, come from the db.
I am exploring the option to convert this part to Angular but so far no dices.

The current view is pretty logic-less and make it relatively clear what is going on.
If I understand well, you are pretty much suggesting to have to break every level in a piece of javascript.

This to me looks messier, less coesive and less readable. Given the data structure that has all the info to display this panel, why do I need to use code in a different file (the module/controller) when the logic is completely view related and very specific of this view? IMHO, the controller should be (and it is right now in the current implementation):

  • get the data from the model
  • pass the model to the view so the framework can render it

Sure I can add a few extra divs and change the CSS, but if this is necessary to make it work with Angular, it feels that Angular is in the way of how it is convenient and elegant to get the things done here.

@mg1075
Copy link

mg1075 commented Aug 31, 2013

I find the databinding in KnockoutJS, which allows both bindings to an html element <div data-bind="foreach: ..."> as well as "containerless control flow syntax", <!-- ko foreach: ... --><!-- /ko -->, to be extraordinarily useful, and think it would be great if Angular could support a similar set of syntax options, very much like the syntax @bowsersenior suggested.

For more details on Knockout's "containerless" option:
http://knockoutjs.com/documentation/foreach-binding.html

@dv336699
Copy link

+1 for @mg1075 virtual syntax.
KnockoutJS makes it easier to deal with dd and nested collections.
e.g http://stackoverflow.com/questions/20062032/nested-table-using-ng-repeat

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

Successfully merging a pull request may close this issue.