angularJS - Repeating tr's in a table, but dynamically adding more rows while looping - angularjs

Since examples always tell more then just words here is what I would like to do in another language
<tr>
<c:forEach items="${items}" var="item">
<td>...</td>
<td>...</td>
<td>...</td>
<c:if test="${item.showWarning}">
</tr><tr><td colspan="3">${item.warning}</td>
</c:if>
</tr>
So this will loop over a set of items and show some properties of these items. If there is a warning, a new row will be added underneath the current row in which the warning will be shown. However, how can I do this in angularJs? If I put a ng-repeat on the tr, it will stop at the first end tag of tr. I have read on some other threads that this is not very easily done, but how can it be done? And yes, I really do want to use a table. Here is my contrived example with angularjs which is obviously not working as I would like it to. Any pointers how this can be done?
JSBin example with tr-ng-repeat

Currently (1.0.7/1.1.5) you can't output data outside the ng-repeat, but version 1.2(see youtube video AngularJS 1.2 and Beyond at 17:30) will bring the following syntax(adapted to your example):
<tr ng-repeat-start="item in items">
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr ng-repeat-end ng-show="item.showWarning">
<td colspan="3">{{item.warning}}</td>
</tr>
The idea is that whatever is between -start and -end will be repeated including the -end element.

One solution that I can think of is having multiple tbody tags within the same table. Here is a discussion on the use of multiple tbody tags within the same table.
So, for your issue, you could have the following setup:
<table ng-controller="ItemController">
<thead>
<th>Name</th>
<th>Description</th>
<th>warning?</th>
</thead>
<tbody ng-repeat="item in items">
<tr>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.warning}}</td>
</tr>
<tr ng-show="item.warning">
<td colspan="3" style="text-align: center">Warning !!!</td>
</tr>
</tbody>
</table>
Repeat the table body as many times as there are entries for the table and within it have two rows - one to actually display the row entry and one to be displayed conditionally.

You can repeat over the tbody
<tbody ng-repeat="item in items">
<tr>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.warning}}</td>
</tr>
<tr ng-show="item.warning">
<td colspan="3">Warning !!!</td>
</tr>
</tbody>
Also you do not need to wrap the ng-show expression in {{}}, you can just use item.warning

Related

ng repeat dynamic with key objet json AngularJS

I have a small problem I would like to set up a ng-repeat dynamic with the values I receive from my JSON object,
First, i made my th from my table with the keys
Secondly, i would like to do my td in dynamic (without putting the name of the key ex: obj.NOM, obj.TYPE ...)
I managed to do something with an Object.keys but logic is not good so I need some help
this is my JSON object ( i show you just the little piece of code that I have a problem )
"HEADER":[
{"NOM":"API-APP","TYPE":"string","DESCRIPTION":"Code application"},
{"NOM":"API-SIGNATURE","TYPE":"string","DESCRIPTION":"Signature de la requete API"},
{"NOM":"API-TIMESTAMP","TYPE":"integer","DESCRIPTION":"Timestamp en microseconde"}]
and this is my ng repeat
<span><b>HEADER</b></span>
<br>
<br>
<table class="table">
<th ng-repeat ="(key, itemHeader) in itemHead.HEADER[0] track by $index">{{key}}</th>
<tr ng-repeat ="(key, itemHeader) in itemHead.HEADER track by $index" >
<td>{{getFirstPropertyValue(itemHeader,$index)}}</td>
</tr>
</table>
I explain i made first a ng-repeat for th with the keys and I would like put my data (3 data per row) in td without put ( .NOM .TYPE .DESCRIPTION)
So I took the function object.key which works very well but that makes me just one element per row but I need 3 elements per row
this is my scope for the function object.key
$scope.getFirstPropertyValue = function(obj,index){
return obj[Object.keys(obj)[index]];
}
and this my result
thanks in advance for your help
<table class="table">
<thead>
<tr>
<th ng-repeat="(key, itemHeader) in itemHead.HEADER[0]">
{{key}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in itemHead.HEADER">
<td ng-repeat="column in row">
{{column}}
</td>
</tr>
</tbody>
</table>

Angularjs smart-table not sorting $index table cells

I have a problem withe the Smart Table AngularJS Sorting, I implemented this on my table as:
The initialized app:
angular.module('myproyApp', ['smart-table'])
The controller side:
$scope.dataList = []; //any json collection with: id, name and description
The view side with st-table directive:
<table class="table table-bordered table-striped" st-table="dataRows" st-safe-src="dataList">
<thead>
<tr>
<th><span class="glyphicon"></span>Q</th>
<th st-sort="name">Name</th>
<th st-sort="descripcion">Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in dataRows">
<td class="col-md-1">{{$index + 1}}</td>
<td class="col-md-4">{{row.name}}</td>
<td class="col-md-4">{{row.description}}</td>
<td>Change</td>
</tr>
</tbody>
</table>
On click the sorting header's cells the table is sorting, but the sorting isn't working for the $index cells. Please if you have any think to include the $index cells to sort. I want not to use the indexes on dataList $scope values, I need that this index will be include only on table view.
Track by is used to link your data with the DOM generation made by ng-repeat. When you add track by you tell angular to generate a single DOM element per data object in the given collection. Because $index has to do with the DOM there is no way to have it relate to a particular data entry. Here's a more detailed explanation.
If you really want to do it without touching your dataList, you could call indexOf in your table:
<tbody>
<tr ng-repeat="row in dataList | orderBy:sortField">
<td class="col-md-1">{{dataRows.indexOf(row)}}</td>
<td class="col-md-4">{{row.name}}</td>
<td class="col-md-4">{{row.description}}</td>
<td>Change</td>
</tr>
</tbody>
Where there is a scoped variable called sortField which is a string that is the name of the field you wish to sort by. I implemented a similar thing in this plunker, using the smart-tables module. http://plnkr.co/edit/AF90dQ
I would advise against this because it quickly becomes expensive for large arrays, and runs into problems if your entries aren't unique.

Angularjs - add additional row inside a tr ng-repeat

Ng-repeat is present on a table row
My query is how can we achieve the following:
<tr ng-repeat="x in y">
Looping here....
</tr>
Now as data object is looping on a <tr>. I have a scenario where I have to display data of 1 row in two <tr>.
Eg.
Table
Data1 data1.2 data1.3 data1.4
Data2 data2.2
Data2b data2.3 data2.4
Data3 data3.2 data3.3 data3.4
Data4 data4.2 data4.3
I.e. display data of 1 row in two
Can't use ng-repeat-end
1) You can combine ng-if with ng-repeat and 2) ng-repeat supports multi-element with ng-repeat-start and ng-repeat-end:
<tr ng-repeat-start="item in [1, 2, 3, 4, 5, 6]">
<td>{{item}}</td><td>something else</td>
</tr>
<tr ng-if="item % 2 === 0" ng-repeat-end>
<td colspan="2">-even</td>
</tr>
Demo
I modified the solution New Dev provided for my purposes & thought I'd share since it really saved me.
I needed a solution to repeat my table header row after every nth row as an alternative to a "frozen/fixed upon scrolling" header row, which just isn't feasible for my use case.
In this example, I'm showing the header row after every 25 rows, but not if it's going to be the last row in the table: (($index+1) != itemCollection.length).
<table class="table table-bordered">
<thead>
<tr>
<th>Column Header 1 - Value</th>
<th>Column Header 2 - Index</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="item in itemCollection">
<td>{{item}}</td>
<td>{{$index}}</td>
</tr>
<tr ng-repeat-end="" ng-if="(($index+1) % 25 === 0) && ($index+1) != itemCollection.length">
<th>Column Header 1 - Value</th>
<th>Column Header 2 - Index</th>
</tr>
</tbody>
</table>
Check out the modified demo. For simplicity's sake, I used an inline collection, so the "not if it's going to be the last row in the table" logic isn't included (as you'll see with the unneeded column header at the very bottom), but you get the picture.
You need to repeat tbody instead of tr.
<tbody ng-repeat="x in y" >
<tr>
<td>{{X. row data}}</td>
<td>{{X. row data 2}}</td>
</tr>
<tr>
<td colspan="2">
{{X. secondRowData}}
</td>
</tr>
</tbody>
<tr ng-repeat-start=x in y>
<td>selectbox here
<tr\>
<tr ng-repeat-end ng-if=somecondition>
<td>label data <\td>
<\tr>
So now we have already used ng-repeat-end. Inside ng-repeat-end i have to display 2 rows for a single iteration.
<tr><td indexis1>selectbox<\td><\tr>
<tr><td indexis2>label primary<\td><\tr>
<tr><td indexis2>label secondary<\td><\tr>
This is a rough code snippet and there are numerous td already present in code.

What does reverse=!reverse means in angular orderby?

I am sorting data with AngularJS. I see in AngularJS documentation https://docs.angularjs.org/api/ng/filter/orderBy an example. I don't understand what does reverse=!reverse means in index.html. Here is the code:
div ng-controller="ExampleController">
<table class="friend">
<tr>
<th>Name
(^)</th>
<th>Phone Number</th>
<th>Age</th>
</tr>
<tr ng-repeat="friend in friends">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>
</table>
</div>
I did as in the example. It works but I don't understand what does the expression reverse=!reverse means?
When you click the link for Phone Number or Age, the sorting of the list is put in reverse order by those columns. reverse=!reverse; just toggles the value of that variable from true to false or from false to true before it's passed to the order function.

table with ng-repeat not displaying correctly

Folks I am using a simple ng-repeat directive to display data in table.
However when the directive renders, the first column takes up all the space and dis-figures the table.
Take a look at the plnkr here :
http://plnkr.co/edit/Hahh4uyQ130zOS8noC3D
please focus on the file layout.html
<table>
<thead>
<tr ng-repeat="element in header" class="header-cells" style="width:{{element.width}}px">
<th drop-down-sort-menu>{{element.column}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="element in body">
<td ng-repeat="h in header" row="{{$parent.$index}}" col="{{$index}}" style="width:{{element.width}}px">{{element[h.column]}}
</td>
</tr>
</tbody>
</table>
I am sure it's something minor. any clues
I believe you problem is that for the headers, you have 4 TRs with only one TH, as opposed to one TR with 4 THs. For this reason, the cells on your headers are not matching the cells on your body.
Do the first ng-repeat at the TH level.
Give it a try and let me know.

Resources