83

This question has been partly addressed here: Angular.js ng-repeat across multiple tr's

However that is just a work-around really, it doesn't actually address the core issue, which is: how can one use ng-repeat across multiple elements without a wrapper?

For example, jquery.accordion requires you to repeat an h3 and div element, how could one do this with ng-repeat?

Community
  • 1
  • 1
geoidesic
  • 4,649
  • 3
  • 39
  • 59

3 Answers3

159

We now have a proper support for this, please see:

AngularJs Commmit

with this change you can now do:

<table>
  <tr ng-repeat-start="item in list">
      <td>I get repeated</td>
  </tr>
  <tr ng-repeat-end>
      <td>I also get repeated</td>
  </tr>
</table>
Coding Enthusiast
  • 3,865
  • 1
  • 27
  • 50
Igor Minar
  • 9,574
  • 3
  • 22
  • 13
  • 1
    In case it helps someone else... This wasn't available in either the stable, nor unstable build of AngularJs on the angularjs.org website. To get this working I had to install the bleeding-edge of Angular.js – the how-to is here: http://stackoverflow.com/questions/17501052/how-can-i-get-a-bleeding-edge-version-of-angular-js-from-github – geoidesic Jul 06 '13 at 12:05
  • 3
    As @geoidesic suggests, this landed after 1.1.5, so watch for it in 1.1.6 (or very likely 1.2.0) – Anson Jul 15 '13 at 11:57
  • 1
    just must add that ng-repeat-start belong to the unstable version currently (aug 13) – bresleveloper Aug 07 '13 at 05:57
  • 1
    And what if the second itself is a "nested" repeated? for example: – Andre Oct 11 '13 at 14:43
  • @Andre Don't do that. Rather create a new directive within your first ng-repeat. – geoidesic Jan 25 '17 at 12:33
22

To answer Andre's question above on more than 2 levels of ng-repeat in a table, you can use multiple ng-repeat-start to accomplish this.

<tr ng-repeat-start="items in list">
   <td>{{items.title}}</td>
</tr>
<tr ng-repeat-start="item in items">
   <td>{{item.subtitle}}</td>
</tr>
<tr ng-repeat-end ng-repeat="value in item.values">
   <td>{{value.col1}}</td>
   <td>{{value.col2}}</td>
</tr>
<tr ng-repeat-end></tr>

Here is a plunker example

hackfan
  • 260
  • 2
  • 8
  • Trying to get this work but I am only getting: Unterminated attribute, found 'ng-repeat-start' but no matching 'ng-repeat-end' found. Does this not work anymore? Using angular 1.5 – stibay Apr 07 '16 at 06:56
3

UPDATE: This answer is outdated. Please see @IgorMinar answer and use standard ng-repeat-start and ng-repeat-end directives.


There are two options:

First option is to create directive that will render several tags and replace source tag (jsfiddle)

<div multi ></div>

angular.module('components').directive('multi', function ($compile) {
return {
    restrict: 'A',
    scope : {
       first : '=',
       last : '=',
    },        
    terminal:true,

    link: function (scope, element, attrs) {
       var tmpl = '', arr = [0,1,2,3]

       // this is instead of your repeater
       for (var i in arr) {
          tmpl +='<div>another div</div>'
       }

       var newElement = angular.element(tmpl);
       $compile(newElement)(scope);
       element.replaceWith(newElement); 
    }
})

Second option is to use updated source code of angular that enables comment style ngRepeat directive (plnkr)

<body ng-controller="MainCtrl">
 <div ng-init="arr=[0,1,2]" ></div>
   <!-- directive: ng-repeat i in arr -->
     <div>{{i}}</div>
     <div>{{ 'foo' }}</div>  
   <!-- /ng-repeat -->

   {{ arr }}

  <div ng-click="arr.push(arr.length)">add</div>
</body>  

vittore
  • 17,449
  • 6
  • 44
  • 82
  • Sounds great. I don't understand any of it though! In your first example I don't see ng-repeat, so I'm not sure how it's relevant (I looked at the fiddle but it is so complicated I can't make head nor tail of it). Your second example is just gobbledigook to me. – geoidesic Jun 03 '13 at 15:44
  • The first example doesn't address the problem because you still end up with a repeating wrapper around the two elements... i.e. the element containing the ng-repeat directive gets repeated too – I just want the inner elements to be repeated. – geoidesic Jun 03 '13 at 16:10
  • @user2448430 no, you don't. `element.replaceWith(newElement);` will replace wrapper tag with what you need. also you can have loop in your directive and add as many tags as you need into tmpl. – vittore Jun 03 '13 at 16:27
  • I disagree. Tried it and it repeats the element containing the ng-repeat directive. Also the second example isn't actually working. The div doesn't repeat, it's just the array that's being output in your plnkr example. – geoidesic Jun 03 '13 at 17:11
  • I like this syntax. It makes sense. I tried to use it here: http://plnkr.co/edit/o8uUncDctntXOynYAC3V?p=preview , but it looks like it's rendering extra tags like this: – JoshGough Jul 15 '13 at 21:13
  • 1
    @JoshGough it does, so I end up adding rule to my css to hide those spans. – vittore Jul 15 '13 at 21:45
  • my example for this http://bresleveloper.blogspot.co.il/2013/08/angularjs-create-directive-with-ng.html – bresleveloper Aug 07 '13 at 07:34
  • @bresleveloper you kinda late for the party, angular included `ng-repeat-start` and `ng-repeat-end` in main branch so it is much easier right now. – vittore Aug 07 '13 at 13:56
  • thx vittore, but currently the bosses dont want the unstable version, so i'll have to w8. btw i had a problem with the replaceWith, and it seems a JQuery problem and not an angular one, i replaced it with empty/append – bresleveloper Aug 12 '13 at 05:18
  • @bresleveloper well it is in a stable one for quite a while already. – vittore Aug 14 '13 at 12:33