I'm working with angular building a table of data which comes from a JSON API call. I'm having to use a nested ngRepeat however I'm seeing strange results where whole table rows are missing when the row has a couple empty strings.
I can reproduce with the following plunk. http://plnkr.co/edit/VCzzzPzfgJ95HmC2f83P?p=preview
<script>
function MyController($scope){
$scope.test = {"rows":[
["one","two","three"],
["one","two","three"],
["one","","three"],
["one","",""],
["","two",""],
["","","three"],
["one","two","three"],
["one","two","three"],
]};};
</script>
<div ng-app ng-controller="MyController">
<table>
<tr ng-repeat="(key,ary) in test.rows">
<td>{{key}}</td>
<td ng-repeat="value in ary">{{value}}</td>
</tr>
</table>
</div>
Notice when an array has two empty strings the nested ngRepeat appears to fail.
Am I going mad? Is there an explaination to this?
Yes. You would need to use track by $index
since you are repeating primitives, or convert it to array of objects. Reason is ng-repeat creates unique id $$hashkey
(and attached to the repeated object as property) for each of the iterated values if it is an object (unless you specify something as track by).
In your case you have primitives so it cannot attach a property itself, so it tries to consider the values repeated as identifier and it finds duplicate when you have multiple empty strings iterated. You would see the same effect when you repeat array of objects with more than one of them is undefined or null as well..
So in this case you can use track by $index
So repeated items will be tracked by its index.
<td ng-repeat="value in ary track by $index">{{value}}</td>
Demo
Much better option always is to convert it to array of objects so you don't run into these kinds of issues. WHen you have a property that uniquely identifies the repeated element (say id
) you can set it as track by
property. When you rebind the array (or refresh the array) angular uses the tracked identifier to determine if it needs to remove the element from DOM and recreate it or just refresh the element that already exists. Many cases where a list is refreshed with the list of items it is always desirable to use a track by with an identifier on the object repeated for performance effectiveness.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With