AngularJS iterating through a multi-layered array with ng-repeat - javascript

I have an issue with the ng-repeat directive when it comes to iterating through an array with multiple layers. Much like a Json object but not quite.
To build the array I use code akin to this:
$scope.dailyData = []
$scope.dailyData[0] = []
$scope.dailyData[0].push([{"today":null,"day2":1,"day3":null,"day4":null,"day5":null,"day6":null,"day7":null,"title":"Queries Built","id":null}])
This is just a sample of what the program actually does, and I do it this way for a specific reason that may or may not be relevant to the question.
This outputs to an array that looks like this.
[[[{"title":"Queries Built","today":null,"day2":1,"day3":null,"day4":null,"id":null}]]]
There are three arrays and an object in the middle. The problem is I can't seem to get the ng-repeat to pull the data from the object.
I want it to output like this:
| Title | Today | Yesterday |
| Queries Built | null | 1 |
But everything I've tried on ng-repeat doesn't seem to work. One such example:
<div ng-repeat="row in dailyData[0]">
<tr>
<td>{{row[0]["title"]}}</td>
<td>{{row["today"]}}</td>
<td>{{row["day2"]}}</td>
<td>{{row["day3"]}}</td>
<td>{{row["day4"]}}</td>
</tr>
</div>
The first row in here is a different method from the others, neither of them works.
Here's a fiddle: https://jsfiddle.net/rms9dv8j/2/

The main problem is that you used a <DIV> tag in the middle of the table, which is probably why the browser didn't render anything.
In this fiddle:
https://jsfiddle.net/5ox7Ledw/
<div ng-repeat="row in dailyData[0][0]">
<tr>
<td>{{row[0]["title"]}}</td>
I simplified the data and moved the ng-repeat into the TR element, while also deleting the erroneous DIV
<tr ng-repeat="row in dailyData">
<td>{{row.title}}</td>

I think you need to restructure your data so that it is in a better format.
You will need to do a nested loop similar to what I've done in this plnkr: http://plnkr.co/edit/CqUHwj?p=info
<div ng-app="module" ng-controller="ctrl">
<div ng-repeat="row in array">
{{row.name}}
<div ng-repeat="row2 in row.array2">
{{row2.name}}
</div>
</div>
</div>
More helpful information can be found in this post:
Nested ng-repeat

Related

How do I display an array / object using ng-repeat

I have an array that looks like the following:
I want to display that using angularJS ng-repeat, showing both count and value for each.
This is currently the HTML and angular I have but nothing displays.
I also don't need to display the 0 index in the array, I want to start from 1 if possible.
<tr ng-class="" ng-repeat="x in vm.data | filter: searchArray">
<td>{{x.value}}</td>
<td>{{x.count}}</td>
</tr>
I went back to the basics and understood that an ng-repeat is just a loop in javascript, and what do you need to do if you want to access data in JavaScript if your array is multi-dimensional? well you do a nested for loop, and thats exactly what I'm doing in this case.
This is the updated html/angularjs that displays the data I need:
<tbody>
<tr ng-repeat="x in vm.data">
<td ng-repeat="y in x">{{y.value}} {{y.count}}</td>
</tr>
</tbody>
Thank you guys again!

two-level hierarchy repeater in angularJS, without any output for the first level

I would like to generate a table in angular, which is nested in a two-level hierarchy which would thus need two nested ng-repeat. An example data structure would be:
Product.Features
Each product would have a list of features, e.g:
iPhone
3G
ScreenSize
Fruit
Color
Size
Texture
I have a list of products, and would like to output as columns the list of features. Hence, the output would be:
<td>3G</td>
<td>ScreenSize</td>
<td>Color</td>
<td>Size</td>
<td>Texture</td>
The problem with this is that when using ng-repeat for the list of products, I cannot generate a blank element. Also, I cannot use ng-repeat on it's own. Some sample code could be (does not work):
<ng-repeat ng-repeat="product in products">
<td ng-repeat="feature in product.feature">
{{feature.Name}}
</td>
</ng-repeat>
Note that the above code is a sample and does not work!
Is this somehow possible? I saw some answers on SO mentioning to use ng-repeat-start but I still could not see how this is possible.
You could use underscore to flatten your list of products, and then you only need one ng-repeat:
In your controller:
$scope.features = _.flatten(_.map(products, function(product) {return product.features}));
$scope.features will be ['3G', 'ScreenSize', 'Color'...]
Then in your view:
<td ng-repeat="feature in features">
{{feature}}
</td>
There's an SO question about flattening an object here.

AngularJS nested ng-repeats with nested bindings

I am trying to make an entirely dynamic angularJS page in such a way that the data-model and header-column-model can be passed in as JSON format and the angular/view can decode everything no matter how many columns, etc.
I have everything (Column Headers, single-Column sorting, multi-Column textbox filtering) working except the data portion where it looks like I want to nest {{bindings}}.
The idea is something like this:
<tr ng-repeat="item in model | filter:filters | orderBy:predicate:reverse">
<td ng-repeat="header in headers">{{{{$parent.item}}.{{header.colName}}}}</td>
</tr>
So that it would resolve to item.column (which is how this is done normally/statically).
However, there doesn't seem to be any embedding/nesting allowed for the double-squiggle references; aka. the first '{{' matches with the first '}}' automatically.
Is there a [good] way to do this?
Try using $eval:
<tr ng-repeat="item in model | filter:filters | orderBy:predicate:reverse">
<td ng-repeat="header in headers">{{$eval('item.' + header.colName}}</td>
</tr>
Here is a plunker showing that concept:
http://plnkr.co/edit/msGuMCCj477jyUAqjChz?p=preview

AngularJS - how to show count 0 when ng-repeat and filter returns no rows

I am trying to print the count of elements filtered through a condition in AngularJS.
I am using ng-repeat to loop over collection and filter it to get counts and it works fine when there is value in it. However, when the filter returns empty result, Angular doesn't render the element and hence, I can't get it to display 0 count.
http://plnkr.co/edit/KNVwf2Yckxf1Qcyzcmea?p=preview
<div ng-repeat="i in iArr|filter:i.name='tim'">{{i.vals.length}}</div>
Does anyone have a clue to make it work in simple fashion.
Edit:
The question How to show a message when filter returns nothing in ng-repeat - AngularJS has a reply which actually solved my question but I don't know how. I am wondering if there is a very simple way to do it.
From that answer:
<select ng-model="shade" ng-options="shade for shade in shades"></select><br>
<ul>
<li ng-repeat="c in filteredColors = (colors | filter:shade)">{{c.name}}</li>
</ul>
<div ng-show="!filteredColors.length">No colors available</div>
The key is in c in filteredColors = (colors | filter:shade). The array result of the filter expression colors | filter:shade is being set to filteredColors, which then becomes available on the $scope object. Because of this, it can be used elsewhere in that controller scope. This is why it can be checked for its length to see if there are no colors.
Here is a working plnkr with solution and some extra
http://plnkr.co/edit/eOmHhR1VWjfYzHYqiEY1?p=preview
<body ng-controller="MainCtrl">
<label><input type="text" ng-model="search.vals">vals</label>
<label><input type="text" ng-model="search.name">name</label>
<div ng-repeat="i in filteredArr = (iArr | filter:search)">{{i.vals}} | {{i.name}}</div>
<div ng-if="!filteredArr.length">0</div>
</body>

How to show a message when filter returns nothing in ng-repeat - AngularJS

I would like to show one div(message) when no items returned on filter(ng-repeat).
Filter is happening based on select box (ng-model). And there are no results for some select options, at that time user should be able to read a message at same place.
Can I use ng-show/hide here? How?
Thanks,
You can also save your filtered array in a variable and then use that variable inside the ng-show expression:
<select ng-model="shade" ng-options="shade for shade in shades"></select><br>
<ul>
<li ng-repeat="c in filteredColors = (colors | filter:shade)">{{c.name}}</li>
</ul>
<div ng-show="!filteredColors.length">No colors available</div>
You can see it in action in this plunker.
You can get the size of array returned by filter using something like
{{(data|filter:query).length}}
You can use this expression for ng-show expression. I am not sure how performant would it be.
There's a simpler solution using just the standard syntax of ngRepeat.
As stated in the official documentation, the ngRepeat accepts an alias for the collection even if filter are applied to it:
<div ng-repeat="model in collection | filter:search | orderBy: 'id' as filtered_result track by model.id">
{{model.name}}
</div>
Note: I added ad additional filter to the example copied from the documentation to have a more complete example.
In this example you can simply use:
<div class="alert alert-info"
ng-show="filtered_result.length == 0">
No items in the collection!
</div>
I tested it with AngularJS 1.5.0, I can't tell when this feature was introduced.

Categories