angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.8k stars 27.48k forks source link

ngRepeat with DL / DD / DT #1891

Closed leeola closed 11 years ago

leeola commented 11 years ago

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 :)

leostera commented 11 years ago

+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 commented 11 years ago

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 commented 11 years ago

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 commented 11 years ago

@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 commented 11 years ago

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 commented 11 years ago

@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 commented 11 years ago

@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 commented 11 years ago

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 commented 11 years ago

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 commented 11 years ago

It is better suggestion. Sent from My Blackberry®

-----Original Message----- From: daegon123 notifications@github.com Date: Mon, 06 May 2013 22:57:16 To: angular/angular.jsangular.js@noreply.github.com Reply-To: "angular/angular.js" reply@reply.github.com 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: https://github.com/angular/angular.js/issues/1891#issuecomment-17524685

xixixao commented 11 years ago

+1, this is a big limitation.

adityamenon commented 11 years ago

:+1: 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 commented 11 years ago

Would #2783 resolve this?

IgorMinar commented 11 years ago

Yes. We have a solution that just landed: e46100f7097d9a8f174bdb9e15d4c6098395c3f2

I'm closing this issue.

gevgeny commented 11 years ago

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 commented 11 years ago

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 commented 11 years ago

@kharnt0x see this puul request https://github.com/angular/angular.js/pull/2859

ChrisCinelli commented 11 years ago

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 commented 11 years ago

@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 commented 11 years ago

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 commented 11 years ago

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 notifications@github.comwrote:

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/angular/angular.js/issues/1891#issuecomment-19644594 .

ChrisCinelli commented 11 years ago

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 commented 11 years ago

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 notifications@github.comwrote:

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/angular/angular.js/issues/1891#issuecomment-19650391 .

ChrisCinelli commented 11 years ago

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):

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 commented 11 years ago

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 commented 11 years ago

+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