angularjs: ng-repeat-start and ng-repeat-end with inner ng-repeat - angularjs

Hi I have a simple use case for ng-repeat-start and end and is working just fine, the problem appears when I want to add an inner ng-repeat.
Here is the my code
<tr ng-repeat-start="obj in rows" >
<td ng-repeat="e in obj.row">{{e}}</td>
</tr>
<tr ng-repeat-end>
<td colspan="4">{{obj.description}}</td>
<tr>
The inner ng-repeat into td element is not working, I'm seeing the ngRepeat comment when I inspect the html source code, but the td elements are not being created.
<!-- ngRepeat: e in obj.row -->
My ugly workaround (given that I know the size of that vector) is:
<tr ng-repeat-start="obj in rows" >
<td>{{obj.row[0]}}</td>
<td>{{obj.row[1]}}</td>
<td>{{obj.row[2]}}</td>
<td>{{obj.row[3]}}</td>
</tr>
<tr ng-repeat-end>
<td colspan="4">{{obj.description}}</td>
<tr>

I am not sure whether you are using angular 1.1.6 or not since ng-repeat-start and ng-repeat-end are not available in 1.1.5 or 1.0.7 yet.
However, you don't actually have to use the new directives to achieve that. You can simply implement it like this for right now:
<table>
<tbody ng-repeat="obj in rows">
<tr ng-repeat="e in obj.row">
<td>{{e}}</td>
</tr>
<tr>
<td colspan="4">{{obj.description}}</td>
<tr>
</tbody>
</table>
You may use ng-repeat-start and ng-repeat-end to reimplement it when AngularJS 1.1.6 version is officially released.
Demo

I think it might be something wrong with your data structure. Using Angular 1.2.1 this works for me
<div ng-app="myApp" ng-controller="myCtrl">
<div class="h" ng-repeat-start="val in data">{{val.title}}</div>
<div ng-repeat="con in val.content">
{{con}}
</div>
<div class="b" ng-repeat-end>footer</div>
</div>
See jsFiddle

You should be able to use index-based iterations to bypass that:
<tr ng-repeat-start="obj in rows" >
<td ng-repeat="e in obj.row">{{obj.row[$index]}}</td>
</tr>
<tr ng-repeat-end>
<!-- ... -->

Related

Div inside tbody with ng-if not filtering the result

First of all let me please accept angular and html is not my trade.
Following is my scenario
<tbody ng-repeat="item in items.ItemList">
<div ng-if="item.variableName == false">
<tr>
<tr/>
<tr ng-show="isPermitted" ng-animate="isPermitted">
<tr/>
</div>
</tbody>
I am trying to control the table rows that I wan't to display with ng-if inside the div and it is not working. By moving ng-if to tbody will filter the rows fine but not at div level.
Unfortunately, I can't move ng-if to the tbody as I have to deal with the else part of the if condition and in that case there is an array inside each item of the repeater that should render rows separately.
Following is the output that I want to have once ng-if condition works appropriately.
P.S. I am not specific to the <div> tag here. I am open to replace div with any other tag as long as it can get me the desired result.
Here someone might say why not ng-if at <tr> level? I am using ng-show and ng-animate so the row with ng-if changes its scope in Doom object and hover over functionality stops working.
<tbody ng-repeat="item in items.ItemList">
<div ng-if="item.variableName == false">
<tr>
<tr/>
<tr ng-show="isPermitted" ng-animate="isPermitted">
<tr/>
</div>
<div ng-if="item.variableName == true">
<tr>
<tr/>
<trng-show="isPermitted" ng-animate="isPermitted">
<tr/>
</div>
</tbody>
I use this and it's work.
Look exemple in the jsfilddle
http://jsfiddle.net/ADukg/12003/
<tbody ng-repeat="item in items.ItemList" ng-show="item.variableName">
<tr>{{item | json}}</tr>
</tbody>
Div won't help you out here as it defies the rules of tbody according to html.
Use ng-container like this instead, it is of no meaning to HTML so it won't defy the rules and you will get your condition fulfilled
<tbody ng-repeat="item in items.ItemList">
<ng-container ng-if="item.variableName == false">
<tr>
<tr/>
<tr ng-show="isPermitted" ng-animate="isPermitted">
<tr/>
</ng-container>
<ng-container ng-if="item.variableName == true">
<tr>
<tr/>
<trng-show="isPermitted" ng-animate="isPermitted">
<tr/>
</ng-container>
</tbody>
Also in your case you can use ng-switch instead of ng-if like this
<tbody ng-repeat="item in items.ItemList" ng-switch="item.variableName">
<ng-container ng-switch-when="false">
<tr>
<tr/>
<tr ng-show="isPermitted" ng-animate="isPermitted">
<tr/>
</ng-container>
<ng-container ng-switch-when == "true">
<tr>
<tr/>
<trng-show="isPermitted" ng-animate="isPermitted">
<tr/>
</ng-container>
</tbody>

Conditionally add row in ng-repeat

I've got a simple repeating table-row in AngularJS
<tr ng-repeat="item in items">
<td>{{ item.prop1 }}</td>
<td>{{ item.prop2 }}</td>
</tr>
My item object has a comment property on it, and if that comment contains a value, I want to display that in a row all by itself on the line right after the rest of the elements and have it span the entire row. Is that type of thing possible? I looked at ng-repeat-end but that doesn't seem to be what I want, and I can't just add and extra <tr> element inside the ng-repeat as that'd be invalid HTML.
You can use ng-repeat's special repeat start and end points via ng-repeat-start and ng-repeat-end.
DEMO
HTML
<table ng-controller="PostController">
<tr ng-repeat-start="post in posts">
<td>{{post.content}}</td>
</tr>
<tr ng-repeat-end ng-repeat="comment in post.comments">
<td>{{comment.content}}</td>
</tr>
</table>
UPDATE: If the comment is a string, then simply remove the ng-repeat at the ng-repeat-end end point and add an ng-if expression that validates the existence of post.comment.
DEMO
HTML
<table ng-controller="PostController">
<tr ng-repeat-start="post in posts">
<td>{{post.content}}</td>
</tr>
<tr ng-repeat-end ng-if="post.comment">
<td>{{post.comment}}</td>
</tr>
</table>

How to obtain index in nested ng-repeats

I have an ng-repeat within a ng-repeat. I am tyring to obtain the index at both levels but am not able to :
<tbody>
<tr ng-repeat="element in body">
<td ng-repeat="h in header" style="width:{{h.width}}px">
<div col="{{$parent.$parent.$index}}" row="{{$parent.$index}}">{{element[h.column]}}</div>
<td>
</tr>
</tbody>
here is a plnkr too.
http://plnkr.co/edit/dGoN43HzQefVpCsp2R3j
The ISSUE is that value of "col" never gets populated. It does not capture the index.
Can anyone assist
You do not have to use $parent, just use $index to get index of inner loop and use indexOf() function of array to get index of outer loop...
HTML
<tr ng-repeat="element in body">
<td ng-repeat="h in header" style="width:{{h.width}}px">
<div col="{{body.indexOf(element)}}" row="{{$index}}">{{element[h.column]}}</div>
<td>
</tr>
UPDATE
Actually using ng-init would much better to get index of outer loop... here you can easily set rowIndex to current index at every turn and use it in inner loop...
<tbody>
<tr ng-repeat="element in body" ng-init="rowIndex = $index">
<td ng-repeat="h in header" style="width:{{h.width}}px">
<div col="{{$index}}" row="{{rowIndex}}">{{element[h.column]}}</div>
<td>
</tr>
</tbody>
here is updated PLUNKER

How to repeat two more rows to each in AngularJS

The following table row is typical.
<tr ng-repeat="item in items">
<td>{{item.id}}</td>
<td>{{item.subject}}</td>
<td>{{item.author}}</td>
<td>{{item.date}}</td>
</tr>
but, how to repeat two rows to each?
<tr ??>
<td rowspan=2>{{item.id}}</td>
<td colspan=2>{{item.subject}}</td>
</tr>
<tr ??>
<td>{{item.author}}</td>
<td>{{item.date}}</td>
</tr>
If you're using AngularJS 1.2+, you can use ng-repeat-start and ng-repeat-end:
<tr ng-repeat-start="item in items">
<td rowspan=2>{{item.id}}</td>
<td colspan=2>{{item.subject}}</td>
</tr>
<tr ng-repeat-end>
<td>{{item.author}}</td>
<td>{{item.date}}</td>
</tr>
See "Special repeat start and end points" in the ngRepeat docs.
Otherwise, you have to resort to some nasty tricks, like wrapping the trs in a tbody element and repeating that.

AngularJS: ng-repeat for 2 x <tr> - can't use a DIV

I am having an issue i need to repeat the following.. as a group
<tr></tr>
<tr></tr>
I can't surround them with a DIV on put the ng-repeat on there as its invalid for TR i.e.
<div ng-repeat="item in items">
<tr></tr>
<tr></tr>
</div>
so i currently have the following implemented
<tr ng-repeat.....></tr>
<tr ng-repeat.....></tr>
but the problem is with this there is a collection of 6 items so the first TR renders 6 times and then 6 times for next ...
I am scratching my head trying to get around this but I just can't figure it out.
It would be nice if there was some sort of Div tag that was used for ng-repeat but didn't render an element to the DOM ??
It looks like the angularjs guys have implemented something along these lines. https://github.com/angular/angular.js/commit/e46100f7097d9a8f174bdb9e15d4c6098395c3f2
So the syntax would be
<tr ng-repeat-start="item in items"></tr>
<tr ng-repeat-end></tr>
You can put the ng-repeat on a tbody element :
<tbody ng-repeat="item in items">
<tr>
<td>{{item.row_one_stuff}}</td>
<td>{{item.more_row_one_stuff}}</td>
</tr>
<tr>
<td>{{item.row_two_stuff}}</td>
<td>{{item.more_row_two_stuff}}</td>
</tr>
</tbody>
<tr ng-repeat-start="item in items">
<td>{{item.data1}}</td>
</tr>
<tr ng-repeat-end>
<td>{{item.data2}}</td>
</tr>

Resources