Extract specific element from ng-repeat - angularjs

I have a list where I display the content of a list using angularjs, like this:
<ul>
<li ng-repeat="result in uploadLogObject[fileUpload.id].log track by $index">
<ul>
<div data-ng-show="result">{{result}}</div>
</ul>
</li>
</ul>
This means that I get a list like this:
* Some data1
* Some data2
* Some data3
* Some data4
Is it possible to take e.g the first element of the list and place outside of the list so that my list is displayed like this?
Some data1
* Some data2
* Some data3
* Some data4
I would guess you would have to do a separate ng-repeat="result in uploadLogObject[fileUpload.id].log track by $index" before the ng-repeat with the list and then display the first content somehow like this? <div data-ng-show="result">{{result}}[0]</div>
Am I wrong or on the right track here?

The documentation of ngRepeat provides a way to do this using ng-repeat-start and ng-repeat-end. :
<div ng-repeat-start="item in items" ng-if="$first">
Header {{ item }}
</div>
<li ng-repeat-end>
body {{ item }}
</li>

Related

How to iterate over arrays in angular 12?

I am trying to iterate over an object that's in an array of an array, however, I'm not able to display the data in the front-end.
I tried this method:
<div *ngFor="let item of events of event | keyvalue">
{{item.key}}:{{item.value}}
</div>
and this one:
<div *ngFor="let item of events of event | json">
Test: {{item}}
</div>
The structure of the JSON data is given in this format.
[
[
{
"age": "age3",
"gender": "gender3"
},
{
"age": "age3",
"gender": "gender3"
}
]
]
You'll have to iterate through each internal array as well, so you'll need a nested *ngFor. Make sure to reference the correct item array in your nested *ngFor.
<div *ngFor = "let item of events">
<div *ngFor = "let x of item">
{{x.age}}:{{x.gender}}
</div>
</div>
It looks likes a nested array, try using multiple ngFor:
<div *ngFor="let event of events">
<div *ngFor="let item of event">
Test: {{item | json}}
</div>
</div>
Otherwise you could try using Array.prototype.flat to flatten the nested array:
this.flattened = this.events.flat();
// ...
<div *ngFor="let item of flattened">
Test: {{item | json}}
</div>
<ng-container> is fine when you want structural logic without polluting the DOM with useless elements.
<ng-container *ngFor="let subArray of array"> <!-- This does not appear in the DOM -->
<div *ngFor="let item of subArray"> <!-- This appears in the DOM -->
{{item.key}}:{{item.value}}
</div>
</ng-container>

Showing JSON-data in AngularJS

This is how my JSON-data looks like:
var data = [
"val1":[
{"DATE":a1, "HEADER":b1, "MESSAGES":c1},
{"DATE":a2, "HEADER":b2, "MESSAGES":c2},
{"DATE":a6, "HEADER":b6, "MESSAGES":c6},
],
"val2":[
{"DATE":a5, "HEADER":b5, "MESSAGES":c5},
{"DATE":a8, "HEADER":b8, "MESSAGES":c8},
],
"val3":[
{"DATE":a3, "HEADER":b3, "MESSAGES":c3},
{"DATE":a4, "HEADER":b4, "MESSAGES":c4},
{"DATE":a7, "HEADER":b7, "MESSAGES":c7},
],
];
Now I want to use this data in html. Therefore I use AngularJS (although this is an old framework). The data is correctly sended to the client side but now I have to display it correctly. I already have this:
<ul>
<li class="message" ng-repeat="messages in data">
{{ messages }}
</li>
</ul>
Now it's showing all the data (which isn't my goal). It should be like this:
Each value (like "val1" and "val2" etc.) should be displayed. Therefore i use ng-repeat.
But now I also want to show the data inside. I thought that I could make another ng-repeat to display all the values of the arrays inside "val1" etc.
But how could I do this and have access to those values?
This HTML should display every item inside val1 array, val2 array and so on:
<ul>
<li class="message" ng-repeat="messages in data">
<span ng-repeat="item in messages">
{{ item }}
<span>
</li>
</ul>
The line <li class="message" ng-repeat="messages in data"> will repeat 1'st level arrays inside data array, and
<span ng-repeat="item in messages">
{{ item }}
<span>
will iterate and display every 2'nd level item, such as {"DATE":a1, "HEADER":b1, "MESSAGES":c1} and so on.

How to sort the dynamic data generating from AngularJS filters?

I am trying to sort the shop titles in alphabetical order right now the data is showing randomly. I am adding the fiddle of that: https://jsfiddle.net/jtdk157s/
enter code here
User the filter OrderBy and specify the property of the Object:
ng-repeat="item in groupedData | filter:categoryFilter | orderBy:['node.location','node.title']
Check working sample:
https://jsfiddle.net/bLvLy1sh/1/
With groupBy filter
<div ng-repeat="(key, items) in groupedData | groupBy: 'node.location' )">
<h2>{{key}}</h2>
<ul>
<li ng-repeat="location in items">
{{ location}}
</li>
</ul>
</div>

How to iterate through an array of arrays in JSON using ng-repeat?

I am trying to iterate over a JSON object userTypes.
For the below code:
In the 1st ng-repeat:
{{user.type}} outputs 'Parent'(as expected),
{{user.options}} outputs '[{"option1":"11QWERT","option2":"22QWERT"}]'(as expected).
But in the 2nd ng-repeat, I am not able to iterate through the user.options and output each of the {{options}}
What should be changed to get the option1 and option2 as the outputs in 2nd ng-repeat ?
JS snippet
var userTypes = [{
"type": 'Parent',
"options": [{
"option1": "11QWERT",
"option2": "22QWERT"
}]
}]
HTML snippet
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<p>{{user.options}}</p>
<li ng-repeat="option in user.options">
<p>
{{option}}
</p>
</li>
</li>
Replace your child <li> with <ul> and then you can iterate user.options like so:
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<ul ng-repeat="(key, value) in user.options[0]">
<p>{{key}}: {{value}}</p>
</ul>
</li>
Or if your options may include more then one object:
<li ng-repeat="user in userTypes">
<p>{{user.type}}</p>
<ul ng-repeat="option in user.options">
<li ng-repeat="(key, value) in option">{{key}}: {{value}}</li>
</ul>
</li>
If you don't need object keys:
<ul ng-repeat="option in user.options">
<li ng-repeat="item in option">{{item}}</li>
</ul>
Fiddle
Extended explanation:
In your example you have <li> tag inside another <li>:
<li ng-repeat="user in userTypes">
<li ng-repeat="option in user.options">
</li>
</li>
Since it is not a valid HTML browser will interprets this markup to following:
<li ng-repeat="user in userTypes">
</li>
<li ng-repeat="option in user.options">
</li>
Since ng-repeat creates new scope for each iteration you can't access user variable in second ng-repeat and iterator wouldn't run.
For this exact JSON input it should be like this:
<li ng-repeat="option in user.options">
<p>
{{option.option1}}
{{option.option2}}
</p>
</li>
However as you said you want non fixed number of options, update your JSON to be like this:
"options":["11QWERT","22QWERT"]
And then your code should work as you wanted it.
You can add each new element to list with simple coma before it.
Since user.options is an array you should loop it again. By doing that you will get an object, with that object you can access your options1 and option2 easily.
please refer working plunker:
http://embed.plnkr.co/5c3i5fY50jLP0fFgxkUX/preview
see through the code if you have any doubt.
Hope this helps
A little aside, but just found out you can render a valid list HTML using ng-repeat-start/end in combination with ng-if="false" for the given array of arrays to flatten them:
<ul>
<script ng-repeat-start="user in userTypes" ng-if="false"></script>
<li ng-repeat="item in user.options">{{item}}</li>
<script ng-repeat-end="" ng-if="false"></script>
</ul>
Just access the propertie of the option object in the second ng-repeat. Like option.option1
You should probably make your user.options an object and not an array containing a single object.
Note the difference between these:
[{"option1":"11QWERT","option2":"22QWERT"}]
{"option1":"11QWERT","option2":"22QWERT"}
You can then iterate the options with an ng-repeat like discussed here:
<li ng-repeat="(key, value) in user.options">
<p>{{ key }}: {{ value }}</p>
</li>

Count group elements using angular-filter

Is it possible using angular-filter "groupBy" (https://github.com/a8m/angular-filter#groupby) to count the elements in each group to use in a "badge" span (of course without using a a function doing the "manual count")
<div class="list-group" ng-repeat="(key, value) in directoryResult | groupBy: 'TableId'">
<a href="#" class="list-group-item active">
<span class="glyphicon glyphicon-transport"></span> {{convertTableid(key)}} <span class="badge">{{directoryResult.length}}</span>
</a>
<div class="list-group" ng-repeat="item in value">
<a href="#" class="list-group-item">
<span class="glyphicon glyphicon-transport"></span> {{item.Text}}
</a>
</div>
</div>
If you do something like:
ng-repeat="(key, value) in directoryResult | groupBy: 'TableId' as result"
then result will be the filtered variable. You can check the length of that for the number of groups.
Update:
Here is a plunker with a groupBy filter.
http://plnkr.co/edit/8jB4wSRtKfVmEsTGZtfV?p=preview
I took an existing filter I found (since angular doesn't have a built in one) and added a length property. The results show up properly.
Update 2:
Another plunker:
http://plnkr.co/edit/iwUkIMjvevja7KyfTrFC?p=preview
Since angular-filter doesn't provide a length property, you have to count it yourself with Object.keys
<div>Number of groups: {{numGroups(result) }} </div>
JS:
$scope.numGroups = function(input){
return Object.keys(input).length;
}
Update 3:
the result contains an object literal: each property is named "key" and its value is a subgroup of the list. So the running solution is:
<div>Number of groups: {{numGroups(result[key]) }} </div>
Update 4
Finally we may get rid completly of the numGroups function, using directly:
<div>Number of groups: {{result[key].length}} </div>
So your first idea was the good one, I had just to adapt it as my groupBy resturn an object literal containing all the goruped lists.

Resources