Reputation: 4201
I have this array:
[
{type:'a', value:'234'},
{type:'a', value:'5566'},
{type:'b', value:'778'},
{type:'c', value:'899'},
{type:'k', value:'5644'}
]
I want to do this iteration:
<div ng-repeat="obj in array">
<h3 ng-bind="obj.type"></h3>
<span ng-bind="obj.value"></span>
</div>
I want the result to be header for each type without duplicates, and under each type I want the values. How can I do it without iterating and creating new arrays?
Desired result:
<div>
<h3>a</h3>
<span>234</span>
<span>234</span>
</div>...
Thanks!
Upvotes: 1
Views: 514
Reputation: 936
I think this should do the trick.
<div ng-repeat="obj in array | unique : 'type'">
<h3 ng-bind="obj.type"></h3>
<span ng-bind="obj.value"></span>
</div>
Check it out and see if it works.
Edit : You would need the angular.filter module for this
Update:
Looking at the updated question, I think it might be difficult for you to achieve the operation given(using a single iteration to list out all the values by unique type).
But you can do one thing, group the array by type using this pure JS function(similar to @Claies answer):
var custom_sort = function(arr){
var a = arr.slice(0);
var ret = [];
var same_type = false;
while (a.length != 0){
var item = a.shift();
if(ret.length > 0){
for(var i = 0; i < ret.length; i++){
if(ret[i].type == item.type){
ret[i].value.push(item.value);
same_type = true;
}
}
}
if(!same_type){
ret.push({type : item.type, value : [item.value]});
}
same_type = false;
}
return ret;
}
The output array that you will get is like this:
[
{ type: 'a', value: [ '234', '5566' ] },
{ type: 'b', value: [ '778' ] },
{ type: 'c', value: [ '899' ] },
{ type: 'k', value: [ '5644' ] }
]
And from there, do the iteration like this:
<div ng-repeat="obj in array">
<h3 ng-bind="obj.type"></h3>
<div ng-repeat="v in obj.value">
<span ng-bind="v"></span>
</div>
</div>
Hope it helps.
Upvotes: 1
Reputation: 22323
The easiest way to achieve the result you are looking for is to use underscore.js _.groupBy
http://underscorejs.org/#groupBy. This will require changing the iterators slightly as well.
Using $scope.groups = _.groupBy($scope.array, "type");
, we get:
{
"a": [{
"type": "a",
"value": "234"
}, {
"type": "a",
"value": "5566"
}],
"b": [{
"type": "b",
"value": "778"
}],
"c": [{
"type": "c",
"value": "899"
}],
"k": [{
"type": "k",
"value": "5644"
}]
}
Using ng-repeat
, we would not get the exact result expected. However, we can use the (key, value)
variation of ng-repeat
to achieve the result we are looking for, something like this:
<div ng-repeat="(type, values) in groups">
<h3 ng-bind="type"></h3>
<span ng-repeat="v in values">
<span ng-bind="v.value"></span>
</span>
</div>
Full Example:
var app = angular.module('stackExample', []);
app.controller('MainCtrl', function($scope) {
$scope.array = [{
type: 'a',
value: '234'
}, {
type: 'a',
value: '5566'
}, {
type: 'b',
value: '778'
}, {
type: 'c',
value: '899'
}, {
type: 'k',
value: '5644'
}];
$scope.groups = _.groupBy($scope.array, "type");
console.log($scope.groups);
});
<script data-require="[email protected]" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
<script data-require="[email protected]" data-semver="1.8.3" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<html ng-app="stackExample">
<body ng-controller="MainCtrl">
<div ng-repeat="(type, values) in groups">
<h3 ng-bind="type"></h3>
<span ng-repeat="v in values">
<span ng-bind="v.value"></span>
</span>
</div>
</body>
</html>
Upvotes: 2
Reputation: 715
I think you have to do some coding for it in your controller to provide a filtered dataSet to ngRepeat.
var dataSet = [
{type:'a', value:'234'},
{type:'a', value:'5566'},
{type:'b', value:'778'},
{type:'c', value:'899'},
{type:'k', value:'5644'}
];
var filteredDataSet = new Array();
dataSet.forEach(function(dataObj){
var tempObject = {};
tempObject.type = dataObj.type;
tempObject.value = new Array(dataObj.value);
var duplicate_key = false;
if (filteredDataSet.length){
filteredDataSet.forEach(function(iObj){
// Push value into a value array of filteredDataSet
// and make the flag duplicate_key value to true to
// prevent the insertion of duplicate object into a
// filteredDataSet array.
if (dataObj.type == iObj.type){
iObj.value.push(dataObj.value);
duplicate_key = true;
}
});
}
// Push non duplicate object by key into a filteredDataSet array
if (duplicate_key == false){
filteredDataSet.push(tempObject);
}
});
$scope.dataSet = filteredDataSet;
And here is your HTML
<div ng-repeat="dataObj in dataSet">
<h1>{{dataObj.type}}</h1>
<div ng-repeat="val in dataObj.value">
<h3>{{val}}</h3>
</div>
</div>
I hope it solve your problem, modification into this code will be highly appreciated thanks.
Upvotes: 0
Reputation: 15292
You need angular-filter.
You can do like this
<div ng-repeat="obj in array | unique:'type' ">
<h3 ng-bind="obj.type"></h3>
<span ng-bind="obj.name"></span>
</div>
Define your app module like this.
var app = angular.module('app', ['angular.filter']);
I have used angular-filter.min.js
Upvotes: 0