Ich führe einen einfachen ng-repeat
über eine JSON-Datei aus und möchte Kategorienamen abrufen. Es gibt ungefähr 100 Objekte, die jeweils zu einer Kategorie gehören - es gibt jedoch nur ungefähr 6 Kategorien.
Mein aktueller Code lautet:
<select ng-model="orderProp" >
<option ng-repeat="place in places" value="{{place.category}}">{{place.category}}</option>
</select>
Die Ausgabe umfasst 100 verschiedene Optionen, meistens Duplikate. Wie kann ich mit Angular prüfen, ob bereits ein {{place.category}}
vorhanden ist, und keine Option erstellen, wenn sie bereits vorhanden ist?
edit: In meinem Javascript $scope.places = JSON data
, nur zur Klarstellung
Sie können den unique - Filter von AngularUI (Quellcode hier: AngularUI unique filter ) verwenden und direkt in den ng-options (oder ng-repeat) verwenden.
<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>
Oder Sie können mit lodash einen eigenen Filter schreiben.
app.filter('unique', function() {
return function (arr, field) {
return _.uniq(arr, function(a) { return a[field]; });
};
});
Sie können "unique" (Aliase: uniq) -Filter in angle.filter module.
verwendung: colection | uniq: 'property'
Sie können auch nach verschachtelten Eigenschaften filtern: colection | uniq: 'property.nested_property'
Was Sie tun können, ist so etwas ..
function MainController ($scope) {
$scope.orders = [
{ id:1, customer: { name: 'foo', id: 10 } },
{ id:2, customer: { name: 'bar', id: 20 } },
{ id:3, customer: { name: 'foo', id: 10 } },
{ id:4, customer: { name: 'bar', id: 20 } },
{ id:5, customer: { name: 'baz', id: 30 } },
];
}
HTML: Wir filtern nach Kundennummer, d. H. Doppelte Kunden entfernen
<th>Customer list: </th>
<tr ng-repeat="order in orders | unique: 'customer.id'" >
<td> {{ order.customer.name }} , {{ order.customer.id }} </td>
</tr>
Ergebnis
Kundenliste:
foo 10
Takt 20
baz 30
dieser Code funktioniert für mich.
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;
};
})
und dann
var colors=$filter('unique')(items,"color");
Wenn Sie Kategorien auflisten möchten, sollten Sie Ihrer -Intervention in der Ansicht explizit mitteilen.
<select ng-model="orderProp" >
<option ng-repeat="category in categories"
value="{{category}}">
{{category}}
</option>
</select>
im Controller:
$scope.categories = $scope.places.reduce(function(sum, place) {
if (sum.indexOf( place.category ) < 0) sum.Push( place.category );
return sum;
}, []);
Ich beschloss, die Antwort von @ thethakuri zu erweitern, um dem einzigartigen Mitglied jede Tiefe zu ermöglichen. Hier ist der Code. Dies ist für diejenigen, die nicht das gesamte AngularUI-Modul nur für diese Funktionalität verwenden möchten. Wenn Sie AngularUI bereits verwenden, ignorieren Sie diese Antwort:
app.filter('unique', function() {
return function(collection, primaryKey) { //no need for secondary key
var output = [],
keys = [];
var splitKeys = primaryKey.split('.'); //split by period
angular.forEach(collection, function(item) {
var key = {};
angular.copy(item, key);
for(var i=0; i<splitKeys.length; i++){
key = key[splitKeys[i]]; //the beauty of loosely typed js :)
}
if(keys.indexOf(key) === -1) {
keys.Push(key);
output.Push(item);
}
});
return output;
};
});
Beispiel
<div ng-repeat="item in items | unique : 'subitem.subitem.subitem.value'"></div>
Hier ist ein einfaches und allgemeines Beispiel.
Der Filter:
sampleApp.filter('unique', function() {
// Take in the collection and which field
// should be unique
// We assume an array of objects here
// NOTE: We are skipping any object which
// contains a duplicated value for that
// particular key. Make sure this is what
// you want!
return function (arr, targetField) {
var values = [],
i,
unique,
l = arr.length,
results = [],
obj;
// Iterate over all objects in the array
// and collect all unique values
for( i = 0; i < arr.length; i++ ) {
obj = arr[i];
// check for uniqueness
unique = true;
for( v = 0; v < values.length; v++ ){
if( obj[targetField] == values[v] ){
unique = false;
}
}
// If this is indeed unique, add its
// value to our values and Push
// it onto the returned array
if( unique ){
values.Push( obj[targetField] );
results.Push( obj );
}
}
return results;
};
})
Das Markup:
<div ng-repeat = "item in items | unique:'name'">
{{ item.name }}
</div>
<script src="your/filters.js"></script>
Ich habe die Verwendung von Set empfohlen, aber leider funktioniert dies nicht für ng-repeat oder Map, da ng-repeat nur mit Array funktioniert. Ignoriere diese Antwort. Wenn Sie jedoch Duplikate herausfiltern müssen, wird angular filters
verwendet, wie in der anderen schon erwähnt wurde. Hier ist der Link zum Einstiegsbereich .
Sie können den ECMAScript 2015 (ES6) -Standard Set Data Structure verwenden , anstelle einer Array-Datenstruktur filtern Sie auf diese Weise wiederholte Werte, wenn Sie dem Set hinzufügen. (Denken Sie daran, dass Sets keine wiederholten Werte zulassen). Wirklich einfach zu bedienen:
var mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add("some text");
var o = {a: 1, b: 2};
mySet.add(o);
mySet.has(1); // true
mySet.has(3); // false, 3 has not been added to the set
mySet.has(5); // true
mySet.has(Math.sqrt(25)); // true
mySet.has("Some Text".toLowerCase()); // true
mySet.has(o); // true
mySet.size; // 4
mySet.delete(5); // removes 5 from the set
mySet.has(5); // false, 5 has been removed
mySet.size; // 3, we just removed one value
Ich hatte ein Array von Strings, keine Objekte, und ich habe diesen Ansatz verwendet:
ng-repeat="name in names | unique"
mit diesem 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();
}
};
}
Wenn Sie eindeutige Daten basierend auf dem verschachtelten Schlüssel erhalten möchten:
app.filter('unique', function() {
return function(collection, primaryKey, secondaryKey) { //optional secondary key
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key;
secondaryKey === undefined ? key = item[primaryKey] : key = item[primaryKey][secondaryKey];
if(keys.indexOf(key) === -1) {
keys.Push(key);
output.Push(item);
}
});
return output;
};
});
Nenne es so:
<div ng-repeat="notify in notifications | unique: 'firstlevel':'secondlevel'">
Es scheint, dass jeder seine eigene Version des unique
-Filters in den Ring wirft, also mache ich dasselbe. Kritik ist sehr willkommen.
angular.module('myFilters', [])
.filter('unique', function () {
return function (items, attr) {
var seen = {};
return items.filter(function (item) {
return (angular.isUndefined(attr) || !item.hasOwnProperty(attr))
? true
: seen[item[attr]] = !seen[item[attr]];
});
};
});
Hier ist nur eine Vorlage, um dies zu tun (die Reihenfolge wird jedoch nicht beibehalten). Außerdem wird das Ergebnis auch bestellt, was in den meisten Fällen nützlich ist:
<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>
Keiner der obigen Filter hat mein Problem behoben, sodass ich den Filter aus dem offiziellen github doc kopieren musste. Und dann wie in den obigen Antworten beschrieben
angular.module('yourAppNameHere').filter('unique', function () {
rückgabefunktion (items, filterOn) {
if (filterOn === false) {
return items;
}
if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
var hashCheck = {}, newItems = [];
var extractValueToCompare = function (item) {
if (angular.isObject(item) && angular.isString(filterOn)) {
return item[filterOn];
} else {
return item;
}
};
angular.forEach(items, function (item) {
var valueToCheck, isDuplicate = false;
for (var i = 0; i < newItems.length; i++) {
if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
newItems.Push(item);
}
});
items = newItems;
}
return items;
};
});
Diesen Filter hinzufügen:
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;
};
});
Aktualisieren Sie Ihr Markup:
<select ng-model="orderProp" >
<option ng-repeat="place in places | unique" value="{{place.category}}">{{place.category}}</option>
</select>
Das mag übertrieben sein, aber es funktioniert für mich.
Array.prototype.contains = function (item, prop) {
var arr = this.valueOf();
if (prop == undefined || prop == null) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == item) {
return true;
}
}
}
else {
for (var i = 0; i < arr.length; i++) {
if (arr[i][prop] == item) return true;
}
}
return false;
}
Array.prototype.distinct = function (prop) {
var arr = this.valueOf();
var ret = [];
for (var i = 0; i < arr.length; i++) {
if (!ret.contains(arr[i][prop], prop)) {
ret.Push(arr[i]);
}
}
arr = [];
arr = ret;
return arr;
}
Die unterschiedliche Funktion hängt von der oben definierten Funktion ab. Es kann als array.distinct(prop);
aufgerufen werden, wobei prop die Eigenschaft ist, die Sie unterscheiden möchten.
Du könntest also einfach $scope.places.distinct("category");
sagen
Erstellen Sie Ihr eigenes Array.
<select name="cmpPro" ng-model="test3.Product" ng-options="q for q in productArray track by q">
<option value="" >Plans</option>
</select>
productArray =[];
angular.forEach($scope.leadDetail, function(value,key){
var index = $scope.productArray.indexOf(value.Product);
if(index === -1)
{
$scope.productArray.Push(value.Product);
}
});