Angular.js ng-repeat across multiple tr's

JavascriptHtmlAngularjs

Javascript Problem Overview


I am using Angular.js for an application that uses hidden trs to simulate a sliding out effect by showing the tr and sliding down the div in the td below. This process worked fantastically using knockout.js when iterating over an array of these rows, because I could use <!-- ko:foreach --> around both tr elements.

With angular, ng-repeat must be applied to an html element, meaning I cannot seem to repeat these double rows using standard methods. My first response to this was to create a directive to represent these double trs, but that fell short because directive templates must have a single root element, but I have two (<tr></tr><tr></tr>).

If anyone with experience with ng-repeat and angular who has cracked this can explain how to solve this problem, I would be greatly appreciative.

(I should also note that attaching ng-repeat to the tbody is an option, but this produces multiple tbodys, and I am assuming that is bad form for standard HTML, although correct me if I'm wrong)

Javascript Solutions


Solution 1 - Javascript

Using ng-repeat on tbody appears to be valid see this post.

Also a quick test through an html validator allowed multiple tbody elements in the same table.

Update: As of at least Angular 1.2 there is an ng-repeat-start and ng-repeat-end to allow repeating a series of elements. See the documentation for more information and thanks to @Onite for the comment!

Solution 2 - Javascript

AngularJS developer @igor-minar answered this in Angular.js ng-repeat across multiple elements.

Miško Hevery recently implemented proper support via ng-repeat-start and ng-repeat-end. This enhancement hasn't been released as of 1.0.7 (stable) and 1.1.5 (unstable).

Update

This is now available in 1.2.0rc1. Check out the official docs and this screencast by John Lindquist.

Solution 3 - Javascript

Having multiple elements might be valid but if you're trying to build a scrollable grid with fixed header / footers, the follow could will not work. This code assumes the following CSS, jquery and AngularJS.

HTML

<table id="tablegrid_ko">
        <thead>
            <tr>
                <th>
                   Product Title
                </th>
                <th>
                </th>
            </tr>
        </thead>

        <tbody ng-repeat="item in itemList">
            <tr ng-repeat="itemUnit in item.itemUnit">
                <td>{{itemUnit.Name}}</td>
            </tr>
        </tbody>
</table>

CSS to build fixed header/footer for scrollable table grid

#tablegrid_ko {
    max-height: 450px;    
}
#tablegrid_ko
{
border-width: 0 0 1px 1px;
border-spacing: 0;
border-collapse: collapse;
border-style: solid;
}

#tablegrid_ko td, #tablegrid_ko th
{
margin: 0;
padding: 4px;
border-width: 1px 1px 0 0;
border-style: solid;
}


#tablegrid_ko{border-collapse:separate}
#tablegrid_ko tfoot,#tablegrid_ko thead{z-index:1}
#tablegrid_ko tbody{z-index:0}
#tablegrid_ko tr{height:20px}
#tablegrid_ko tr >td,#tablegrid_ko tr >th{
border-width:1px;border-style:outset;height:20px;
max-height:20px;xwidth:45px;xmin-width:45px;xmax-width:45px;white-space:nowrap;overflow:hidden;padding:3px}

#tablegrid_ko tr >th{
background-color:#999;border-color:#2c85b1 #18475f #18475f #2c85b1;color:#fff;font-weight:bold}
#tablegrid_ko tr >td{background-color:#fff}
#tablegrid_ko tr:nth-child(odd)>td{background-color:#f3f3f3;border-color:#fff #e6e6e6 #e6e6e6 #fff}
#tablegrid_ko tr:nth-child(even)>td{background-color:#ddd;border-color:#eaeaea #d0d0d0 #d0d0d0 #eaeaea}

div.scrollable-table-wrapper{
background:#268;border:1px solid #268;
display:inline-block;height:285px;min-height:285px;
max-height:285px;width:550px;position:relative;overflow:hidden;padding:26px 0}

div.scrollable-table-wrapper table{position:static}
div.scrollable-table-wrapper tfoot,div.scrollable-table-wrapper thead{position:absolute}
div.scrollable-table-wrapper thead{left:0;top:0}
div.scrollable-table-wrapper tfoot{left:0;bottom:0}
div.scrollable-table-wrapper tbody{display:block;position:relative;overflow-y:scroll;height:283px;width:550px}

Jquery to bind horizontal scrolling of tbody, this does not work because tbody repeats during ng-repeat.

$(function ($) {

$.fn.tablegrid = function () {
    

        var $table = $(this);
        var $thead = $table.find('thead');
        var $tbody = $table.find('tbody');
        var $tfoot = $table.find('tfoot');

        $table.wrap("<div class='scrollable-table-wrapper'></div>");

        $tbody.bind('scroll', function (ev) {
            var $css = { 'left': -ev.target.scrollLeft };
            $thead.css($css);
            //$tfoot.css($css);
        });
    

    }; // plugin function



}(jQuery));

Solution 4 - Javascript

You can do it in this way, as I showed in this answer: https://stackoverflow.com/a/26420732/769900

<tr ng-repeat="m in myData">
   <td>{{m.Name}}</td>
   <td>{{m.LastName}}</td>

   <td ng-if="$first" rowspan="{{myData.length}}">
       <ul>
           <li ng-repeat="d in days">
               {{d.hours}}
           </li>
       </ul>
   </td> 
</tr>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionthegreenpizzaView Question on Stackoverflow
Solution 1 - JavascriptGloopyView Answer on Stackoverflow
Solution 2 - JavascriptAnsonView Answer on Stackoverflow
Solution 3 - JavascriptphanfView Answer on Stackoverflow
Solution 4 - JavascriptJeff TianView Answer on Stackoverflow