Sort subarrays in array with AngularJS - arrays

If I have a dataset that contains an array of objects, with each object having an array inside of them, how can I sort the subarrays by their properties? For example, here is some sample music data, it has 2 albums with tracks within them:
albums: [
{
type: "album",
name: "Brothers",
tracks: [
{
type: "track",
name: "Everlasting Light"
},
{
type: "track",
name: "Next Girl"
},
{
type: "track",
name: "Tighten Up"
}
]
},
{
type: "album",
name: "Listen",
tracks: [
{
type: "track",
name: "Around Town"
},
{
type: "track",
name: "Forgive & Forget"
}
]
}
]
The result would look like this:
- Around Town
- Everlasting Light
- Forgive & Forget
- Next Girl
- Tighten Up
Is there any way I can use an ng-repeat to create an alphabetically sorted list of music tracks?
I'd imagine it working something like below, but I tried with no success.
<p ng-repeat="track in albums.tracks">{{track.name}}</p>

Since you need only the tracks of albums, you should merge all the tracks in a single array and then just sort it alphabetically. Here's is a snippet working:
var app = angular.module('app', []);
app.controller('mainCtrl', function($scope) {
$scope.albums = [
{
"type":"album",
"name":"Brothers",
"tracks":[
{
"type":"track",
"name":"Everlasting Light"
},
{
"type":"track",
"name":"Next Girl"
},
{
"type":"track",
"name":"Tighten Up"
}
]
},
{
"type":"album",
"name":"Listen",
"tracks":[
{
"type":"track",
"name":"Around Town"
},
{
"type":"track",
"name":"Forgive & Forget"
}
]
}
];
$scope.tracks = [];
angular.forEach($scope.albums, function(value) {
$scope.tracks = $scope.tracks.concat(value.tracks);
});
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js">
</script>
</head>
<body ng-controller="mainCtrl">
<div ng-repeat="track in tracks | orderBy:'name'">
<span ng-bind="track.name"></span>
</div>
</body>
</html>

You can use the orderby filter to sort your list based on a property. The angular website has more info on this https://docs.angularjs.org/api/ng/filter/orderBy
Here is a plunker that might help, https://plnkr.co/edit/goxNA9PvBeFL0hyWp9hR?p=preview
You can use the filter directly in your html to sort by a property.
<div ng-repeat="album in albums">
<h2>{{album.name}}</h2>
<div ng-repeat="track in album.tracks | orderBy:'name'">
{{track.name}}
</div>
</div>

Related

Dispaly object of array values in angular 2 using Ngfor

I have a array of object values.i am using a group by method to group the values based on type.it gives a object of array values.i struggle to how to display the values using Ngfor in angular 2.
i have a following structure value.
{
[
{
id:1
body:"value1"
type:"name"
},
{
id:2
body:"value1"
type:"id"
}
],
[
{
id:3
body:"value1"
type:"name"
},
{
id:4
body:"value1"
type:"id"
},
{
id:5
body:"value1"
type:"name"
}
],
[
{
id:6
body:"value1"
type:"id"
},
{
id:7
body:"value1"
type:"fname"
},
{
id:8
body:"value1"
type:"fname"
}
]
}
And my html code is.
<div *ngFor="let value of result">
{{value.body}}
</div>
ngFor only works on Array element. Also your current JSON seems to invalid. Though You can easily flatten the arrays into single array and use ngFor to render it on DOM
<div *ngFor="let value of flattenArray">
{{value.body}}
</div>
Component
flattenArray = [];
//after retrieving result, create flatten array.
for(let value of result){
this.flattenArray.conact(value);
}
what you have is not an array of objects, it's even not a JSON (check it with https://jsonlint.com/),
when you replace first {} with [], (and add comas, ofcourse!) all will works fine, here is valid json:
[
[
{
id:1,
body:"value1",
type:"name"
},
{
id:2,
body:"value1",
type:"id"
}
],
[
{
id:3,
body:"value1",
type:"name"
},
{
id:4,
body:"value1",
type:"id"
},
{
id:5,
body:"value1",
type:"name"
}
]
]
and then in angular view:
<div *ngFor="let items of result">
<div *ngFor="let value of items">
{{value.body}}
</div>
</div>
Thanks for everyone response.i got a solution for the question.
let value = _.groupBy(data, "type");
for (let key in value) {
content.push({ key: key, value: value[key] });
}
and my html is
<div *ngFor="let keys of content">
<div *ngFor="let value of keys.value">
{{value.body}}
</div>
</div>

How to get Unique values from json using angular js?

Response code :
In this response eid is repeated, but I want to dispaly only once.
{"response": [
{
"sid": 1,
"eid": "AA",
"ename": "AA11"
},{
"sid": 2,
"eid": "AA",
"ename": "AA11"
}
],
"status": "success"
}
You could use the unique filter from AngularUI
<p ng-repeat="x in data.response | unique: 'ename'">{{x.ename}}</p>
DEMO
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<p ng-repeat="x in data.response | unique: 'ename'">{{x.ename}}</p>
<script>
//App declaration
var app = angular.module('myApp',['ui.filters']);
//Controller Declaration
app.controller('myCtrl',function($scope){
$scope.data = {"response": [
{
"sid": 1,
"eid": "AA",
"ename": "AA11"
},{
"sid": 2,
"eid": "AA",
"ename": "AA11"
}
],
"status": "success"
};
});
</script>
</body>
</html>
There is no magic way. This task should primarily be completed before the response lands the client (on server).
What you can do is make a function which handles the response the way you prefer.
e.g.
//Removes duplicates of eid property
function getUniqueValues(input) {
var output = [];
function existsInOutput(element) {
return output.map(function(val) {
return val.eid
}).includes(element.eid)
};
angular.forEach(input,function(val, key) {
if (!existsInOutput(val)) {
output.push(val);
}
})
return output;
}

How to filter nested ng-repeat by parent id?

I have an array
lists = [{"id":"1234"},{"id":"5423"},{"id":"65342"}]
And array with contents:
contents = [{"id":"1","listId":"1234"},{"id":"2","listId":"5423"}]
How can I filter ng-repeat for "contents" inside ng-repeat for "lists" and filter "contents" by content.listID equal list.id?
You should probably be doing this mapping in the controller rather than in the view, but the below example will show you how to do it.
(function() {
'use strict';
angular
.module('exampleApp', [])
.controller('ExampleController', ExampleController);
function ExampleController() {
var vm = this;
vm.lists = [{
"id": "1234"
}, {
"id": "5423"
}, {
"id": "65342"
}]
vm.contents = [{
"id": "1",
"listId": "1234"
}, {
"id": "2",
"listId": "5423"
}]
}
ExampleController.$inject = [];
})();
<!DOCTYPE html>
<html ng-app='exampleApp'>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>
</head>
<body ng-controller="ExampleController as vm">
<div ng-repeat="item in vm.lists">
<p ng-repeat="content in vm.contents | filter:{ listId: item.id }">Content ID: {{content.id}} Lists ID: {{item.id}}</p>
</div>
</body>
</html>
ng-repeat="e in contents | filter: {listId: lists.id}"
You will have to parent id to child array and child array will be filtered for that parent id. plnk for similar example.
Regards.

Getting Nested values in angular with a json feed

I have the following json example:
posts: [
{
title: Post Title,
- cat: [
- {
name: "Category Name",
}
],
I am able to get the title in Angular using {{post.title}}
However when I try to get {{post.cat.name}} its not working and its returning "0"
That's because cat is an array. You should handle it like that.
{{posts.cat[0].name}} if you want the first element in that array.
Usually for arrays you'll use ng-repeat though:
<span ng-repeat="cat in posts.cat">{{cat.name}}</span>
try this.
var app = angular.module("app",[]);
app.controller("MyCtrl" , function($scope){
$scope.posts=[
{
title: "Post Title",
cat: [
{
name: "Category Name",
}
]
},
{
title: "Post Title2",
cat: [
{
name: "Category Name2",
}
]
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<table>
<tr ng-repeat="p in posts" >
<td >{{p.title}}</td>
<td >{{p.cat[0].name}}</td>
</tr>
</table>
</div>
cat is an array, so to get the name of the first object in that array, you would have to use:
{{post.cat[0].name}}

Create an unordered list n-levels deep using AngularJS

While going through some AngularJS examples, I see how easy it is to repeat and create structures. However, I couldn't figure out how to do the following.
Assume we have a json structure like
{
"Asia": {
"India": {
"Bangalore": {},
"Mumbai": {},
"New Delhi": {}
},
"China": {
"Beijing": {},
"Shanghai": {}
}
},
"Europe": {
"France": {
"Paris": {}
},
"Germany": {
"Berlin": {}
}
}
}
What I want to do is - Convert this JSON structure to an Unordered list - The depth of this kind of structure is not known, and can possibly go deeper. How do I perform repeats dynamically using Angular JS?
Your JSON is poorly structured, you're using property names to carry data.
What you really want is something like this:
$scope.continents = [
{
name: 'Asia',
countries: [
{
name: 'India',
cities: [
'Bangalore',
'Mumbai',
'New Delhi'
]
},
{
name: 'China',
cities: [
'Beijing',
'Shanghai'
]
},
]
},
{
name: 'Europe',
countries: [
{
name: 'France',
cities: [
'Peris'
]
},
{
name: 'Germany',
cities: [
'Berlin'
]
},
]
}
];
That said... what it sounds like you're looking to do is create a recursive tree directive of some sort. That gets a little tricky. You'll need to normalize your structure a bit so you can recursively examine it. Then you'll have to create two directives. One for a list, and one for an item:
Here is an example of what I mean...
function Item(name, items) {
this.name = name;
this.items = items || [];
}
app.controller('MainCtrl', function($scope) {
$scope.items = [
new Item('test'),
new Item('foo', [
new Item('foo-1'),
new Item('foo-2', [
new Item('foo-2-1'),
new Item('foo-2-2')
])
]),
new Item('whatever')
];
});
app.directive('tree', function() {
return {
template: '<ul><tree-node ng-repeat="item in items"></tree-node></ul>',
restrict: 'E',
replace: true,
scope: {
items: '=items'
}
};
});
app.directive('treeNode', function($compile) {
return {
restrict: 'E',
template: '<li>{{item.name}}</li>',
link: function(scope, elm, attrs) {
//MAGIC HERE!!!: this will do the work of inserting the next set of nodes.
if (scope.item.items.length > 0) {
var children = $compile('<tree items="item.items"></tree>')(scope);
elm.append(children);
}
}
};
});
In case anyone is interested in the "least-effort" way to do this without creating a directive (not that you shouldn't, but just offering a variation), here is a simple example:
http://jsbin.com/hokupe/1/edit
Also here's a blog post and a 10-15 minutes video on how it works:
http://gurustop.net/blog/2014/07/15/angularjs-using-templates-ng-include-create-infinite-tree/
Sample Code:
<script type="text/ng-template" id="treeLevel.html">
<ul>
<li ng-repeat="item in items">
<input type="checkbox"
name="itemSelection"
ng-model="item._Selected" />
{{item.text}}
<div ng-include=" 'treeLevel.html'"
onload="items = item.children">
</div>
</li>
</ul>
</script>
<div ng-include=" 'treeLevel.html' "
onload="items = sourceItems">
</div>

Resources