I\'m running a simple ng-repeat
over a JSON file and want to get category names. There are about 100 objects, each belonging to a category - but there are only
Here's a template-only way to do it (it's not maintaining the order, though). Plus, the result will be ordered as well, which is useful in most cases:
<select ng-model="orderProp" >
<option ng-repeat="place in places | orderBy:'category' as sortedPlaces" data-ng-if="sortedPlaces[$index-1].category != place.category" value="{{place.category}}">
{{place.category}}
</option>
</select>
You could use the unique filter from AngularUI (source code available here: AngularUI unique filter) and use it directly in the ng-options (or ng-repeat).
<select ng-model="orderProp" ng-options="place.category for place in places | unique:'category'">
<option value="0">Default</option>
// unique options from the categories
</select>
this code works for me.
app.filter('unique', function() {
return function (arr, field) {
var o = {}, i, l = arr.length, r = [];
for(i=0; i<l;i+=1) {
o[arr[i][field]] = arr[i];
}
for(i in o) {
r.push(o[i]);
}
return r;
};
})
and then
var colors=$filter('unique')(items,"color");
Or you can write your own filter using lodash.
app.filter('unique', function() {
return function (arr, field) {
return _.uniq(arr, function(a) { return a[field]; });
};
});
Add this filter:
app.filter('unique', function () {
return function ( collection, keyname) {
var output = [],
keys = []
found = [];
if (!keyname) {
angular.forEach(collection, function (row) {
var is_found = false;
angular.forEach(found, function (foundRow) {
if (foundRow == row) {
is_found = true;
}
});
if (is_found) { return; }
found.push(row);
output.push(row);
});
}
else {
angular.forEach(collection, function (row) {
var item = row[keyname];
if (item === null || item === undefined) return;
if (keys.indexOf(item) === -1) {
keys.push(item);
output.push(row);
}
});
}
return output;
};
});
Update your markup:
<select ng-model="orderProp" >
<option ng-repeat="place in places | unique" value="{{place.category}}">{{place.category}}</option>
</select>
I had an array of strings, not objects and i used this approach:
ng-repeat="name in names | unique"
with this filter:
angular.module('app').filter('unique', unique);
function unique(){
return function(arry){
Array.prototype.getUnique = function(){
var u = {}, a = [];
for(var i = 0, l = this.length; i < l; ++i){
if(u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
};
if(arry === undefined || arry.length === 0){
return '';
}
else {
return arry.getUnique();
}
};
}