Ich möchte filter
in angle verwenden und nach mehreren Werten filtern. Wenn einer der Werte vorhanden ist, sollte er angezeigt werden.
Ich habe zum Beispiel diese Struktur:
Ein Objekt movie
mit der Eigenschaft genres
und ich möchte nach Action
und Comedy
filtern.
Ich weiß, ich kann filter:({genres: 'Action'} || {genres: 'Comedy'})
, aber was tun, wenn ich es dynamisch filtern möchte. Z.B. filter: variableX
Wie kann ich variableX
im $scope
einstellen, wenn ich ein Array der Genres habe, die ich filtern muss?
Ich könnte es als String konstruieren und dann eine eval()
machen, aber ich möchte eval () nicht verwenden ...
Ich würde einfach einen benutzerdefinierten Filter erstellen. Sie sind nicht so schwer.
angular.module('myFilters', []).
filter('bygenre', function() {
return function(movies,genres) {
var out = [];
// Filter logic here, adding matches to the out var.
return out;
}
});
<h1>Movies</h1>
<div ng-init="movies = [
{title:'Man on the Moon', genre:'action'},
{title:'Meet the Robinsons', genre:'family'},
{title:'Sphere', genre:'action'}
];" />
<input type="checkbox" ng-model="genrefilters.action" />Action
<br />
<input type="checkbox" ng-model="genrefilters.family" />Family
<br />{{genrefilters.action}}::{{genrefilters.family}}
<ul>
<li ng-repeat="movie in movies | bygenre:genrefilters">{{movie.title}}: {{movie.genre}}</li>
</ul>
Bearbeiten Hier ist der Link: Erstellen von Winkelfiltern
UPDATE: Hier ist eine Geige die eine genaue Demo meines Vorschlags hat.
Sie können eine Controller-Funktion zum Filtern verwenden.
function MoviesCtrl($scope) {
$scope.movies = [{name:'Shrek', genre:'Comedy'},
{name:'Die Hard', genre:'Action'},
{name:'The Godfather', genre:'Drama'}];
$scope.selectedGenres = ['Action','Drama'];
$scope.filterByGenres = function(movie) {
return ($scope.selectedGenres.indexOf(movie.genre) !== -1);
};
}
HTML:
<div ng-controller="MoviesCtrl">
<ul>
<li ng-repeat="movie in movies | filter:filterByGenres">
{{ movie.name }} {{ movie.genre }}
</li>
</ul>
</div>
Das Erstellen eines benutzerdefinierten Filters ist hier möglicherweise übertrieben. Sie können einfach einen benutzerdefinierten Vergleicher übergeben, wenn Sie mehrere Werte wie die folgenden Werte haben:
$scope.selectedGenres = "Action, Drama";
$scope.containsComparator = function(expected, actual){
return actual.indexOf(expected) > -1;
};
dann im filter:
filter:{name:selectedGenres}:containsComparator
Hier ist die Implementierung eines benutzerdefinierten Filters, der die Daten mit einem Array von Werten filtert. Er unterstützt mehrere Schlüsselobjekte mit einem Array und einem einzelnen Wert von Schlüsseln. Wie bereits erwähnt, unterstützt inangularJS API AngularJS-Filter Doc mehrere Schlüsselfilter mit Einzelwerten, aber unterhalb des benutzerdefinierten Filters werden dieselben Funktionen wie "angleJS" unterstützt und es werden auch Array-Werte und Kombinationen von Array- und Einzelwerten von Schlüsseln unterstützt Ausschnitt unten,
myApp.filter('filterMultiple',['$filter',function ($filter) {
return function (items, keyObj) {
var filterObj = {
data:items,
filteredData:[],
applyFilter : function(obj,key){
var fData = [];
if (this.filteredData.length == 0)
this.filteredData = this.data;
if (obj){
var fObj = {};
if (!angular.isArray(obj)){
fObj[key] = obj;
fData = fData.concat($filter('filter')(this.filteredData,fObj));
} else if (angular.isArray(obj)){
if (obj.length > 0){
for (var i=0;i<obj.length;i++){
if (angular.isDefined(obj[i])){
fObj[key] = obj[i];
fData = fData.concat($filter('filter')(this.filteredData,fObj));
}
}
}
}
if (fData.length > 0){
this.filteredData = fData;
}
}
}
};
if (keyObj){
angular.forEach(keyObj,function(obj,key){
filterObj.applyFilter(obj,key);
});
}
return filterObj.filteredData;
}
}]);
Verwendungszweck:
arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
Hier ist ein Geigenbeispiel mit der Implementierung des obigen "filterMutiple" benutzerdefinierten Filters . ::: Fiddle-Beispiel :::
Wenn Sie nach Array of Objects filtern möchten, können Sie geben
filter:({genres: 'Action', key :value }.
Die einzelne Eigenschaft wird nach einem bestimmten Filter für diese Eigenschaft gefiltert.
Wenn Sie jedoch so etwas nach einzelnen Eigenschaften filtern und global nach allen Eigenschaften filtern möchten, können Sie so etwas tun.
<tr ng-repeat="supp in $data | filter : filterObject | filter : search">
~ Atul
Ich habe einige Zeit damit verbracht, und dank @chrismarx habe ich gesehen, dass die Standardvariable von __filterFilter
des Winkels es Ihnen erlaubt, Ihren eigenen Vergleicher zu übergeben. Hier ist der bearbeitete Komparator für mehrere Werte:
function hasCustomToString(obj) {
return angular.isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
}
var comparator = function (actual, expected) {
if (angular.isUndefined(actual)) {
// No substring matching against `undefined`
return false;
}
if ((actual === null) || (expected === null)) {
// No substring matching against `null`; only match against `null`
return actual === expected;
}
// I edited this to check if not array
if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
// Should not compare primitives against objects, unless they have custom `toString` method
return false;
}
// This is where magic happens
actual = angular.lowercase('' + actual);
if (angular.isArray(expected)) {
var match = false;
expected.forEach(function (e) {
e = angular.lowercase('' + e);
if (actual.indexOf(e) !== -1) {
match = true;
}
});
return match;
} else {
expected = angular.lowercase('' + expected);
return actual.indexOf(expected) !== -1;
}
};
Und wenn wir einen benutzerdefinierten Filter für DRY erstellen möchten:
angular.module('myApp')
.filter('filterWithOr', function ($filter) {
var comparator = function (actual, expected) {
if (angular.isUndefined(actual)) {
// No substring matching against `undefined`
return false;
}
if ((actual === null) || (expected === null)) {
// No substring matching against `null`; only match against `null`
return actual === expected;
}
if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
// Should not compare primitives against objects, unless they have custom `toString` method
return false;
}
console.log('ACTUAL EXPECTED')
console.log(actual)
console.log(expected)
actual = angular.lowercase('' + actual);
if (angular.isArray(expected)) {
var match = false;
expected.forEach(function (e) {
console.log('forEach')
console.log(e)
e = angular.lowercase('' + e);
if (actual.indexOf(e) !== -1) {
match = true;
}
});
return match;
} else {
expected = angular.lowercase('' + expected);
return actual.indexOf(expected) !== -1;
}
};
return function (array, expression) {
return $filter('filter')(array, expression, comparator);
};
});
Und dann können wir es überall einsetzen, wo wir wollen:
$scope.list=[
{name:'Jack Bauer'},
{name:'Chuck Norris'},
{name:'Superman'},
{name:'Batman'},
{name:'Spiderman'},
{name:'Hulk'}
];
<ul>
<li ng-repeat="item in list | filterWithOr:{name:['Jack','Chuck']}">
{{item.name}}
</li>
</ul>
Zum Schluss noch ein plunkr .
Hinweis: Das erwartete Array sollte nur einfache Objekte wie String, Number usw. enthalten.
sie können den searchField-Filter von angle.filter verwenden.
JS:
$scope.users = [
{ first_name: 'Sharon', last_name: 'Melendez' },
{ first_name: 'Edmundo', last_name: 'Hepler' },
{ first_name: 'Marsha', last_name: 'Letourneau' }
];
HTML:
<input ng-model="search" placeholder="search by full name"/>
<th ng-repeat="user in users | searchField: 'first_name': 'last_name' | filter: search">
{{ user.first_name }} {{ user.last_name }}
</th>
<!-- so now you can search by full name -->
Die schnellste Lösung, die ich gefunden habe, ist die Verwendung des filterBy
-Filters von angle-filter , zum Beispiel:
<input type="text" placeholder="Search by name or genre" ng-model="ctrl.search"/>
<ul>
<li ng-repeat="movie in ctrl.movies | filterBy: ['name', 'genre']: ctrl.search">
{{movie.name}} ({{movie.genre}}) - {{movie.rating}}
</li>
</ul>
Der Vorteil ist, dass angle-filter eine ziemlich beliebte Bibliothek ist (~ 2,6k Sterne auf GitHub), die noch aktiv entwickelt und gepflegt wird. Es sollte also in Ordnung sein, sie als Abhängigkeit zu Ihrem Projekt hinzuzufügen.
Sie können auch ngIf
verwenden, wenn die Situation dies zulässt:
<div ng-repeat="p in [
{ name: 'Justin' },
{ name: 'Jimi' },
{ name: 'Bob' }
]" ng-if="['Jimi', 'Bob'].indexOf(e.name) > -1">
{{ p.name }} is cool
</div>
Ich glaube, das ist, wonach Sie suchen:
<div>{{ (collection | fitler1:args) + (collection | filter2:args) }}</div>
Nehmen wir an, Sie haben zwei Arrays, einen für Film und einen für Genre
Verwenden Sie den Filter einfach als: filter:{genres: genres.type}
Hier haben Genres, die als Array und Typ dienen, einen Wert für das Genre
Bitte versuchen Sie das
var m = angular.module('yourModuleName');
m.filter('advancefilter', ['$filter', function($filter){
return function(data, text){
var textArr = text.split(' ');
angular.forEach(textArr, function(test){
if(test){
data = $filter('filter')(data, test);
}
});
return data;
}
}]);
Ich hatte eine ähnliche Situation. Das Schreiben von benutzerdefinierten Filtern funktionierte für mich. Hoffe das hilft!
JS:
App.filter('searchMovies', function() {
return function (items, letter) {
var resulsts = [];
var itemMatch = new RegExp(letter, 'i');
for (var i = 0; i < items.length; i++) {
var item = items[i];
if ( itemMatch.test(item.name) || itemMatch.test(item.genre)) {
results.Push(item);
}
}
return results;
};
});
HTML:
<div ng-controller="MoviesCtrl">
<ul>
<li ng-repeat="movie in movies | searchMovies:filterByGenres">
{{ movie.name }} {{ movie.genre }}
</li>
</ul>
</div>
Zu spät, um der Party beizutreten, kann aber jemandem helfen:
Wir können dies in zwei Schritten tun, zuerst nach der ersten Eigenschaft filtern und dann nach dem zweiten Filter verketten:
$scope.filterd = $filter('filter')($scope.empList, { dept: "account" });
$scope.filterd = $scope.filterd.concat($filter('filter')($scope.empList, { dept: "sales" }));
Sehen Sie die Arbeitsgeige mit mehreren Eigenschaftenfiltern
Winkel- oder Filtermodul
$filter('orFilter')([{..}, {..} ...], {arg1, arg2, ...}, false)
hier ist der Link: https://github.com/webyonet/angular-or-filter
Ich habe dies für Strings UND Funktionalität geschrieben (ich weiß, es ist nicht die Frage, aber ich habe danach gesucht und bin hierher gekommen), vielleicht kann es erweitert werden.
String.prototype.contains = function(str) {
return this.indexOf(str) != -1;
};
String.prototype.containsAll = function(strArray) {
for (var i = 0; i < strArray.length; i++) {
if (!this.contains(strArray[i])) {
return false;
}
}
return true;
}
app.filter('filterMultiple', function() {
return function(items, filterDict) {
return items.filter(function(item) {
for (filterKey in filterDict) {
if (filterDict[filterKey] instanceof Array) {
if (!item[filterKey].containsAll(filterDict[filterKey])) {
return false;
}
} else {
if (!item[filterKey].contains(filterDict[filterKey])) {
return false;
}
}
}
return true;
});
};
});
Verwendungszweck:
<li ng-repeat="x in array | filterMultiple:{key1: value1, key2:[value21, value22]}">{{x.name}}</li>
Hier ist mein Beispiel, wie Filter und Anweisungen für die Tabelle jsfiddle erstellt werden.
direktive get list (datas) und Tabelle mit Filtern erstellen
<div ng-app="autoDrops" ng-controller="HomeController">
<div class="row">
<div class="col-md-12">
<h1>{{title}}</h1>
<ng-Multiselect array-List="datas"></ng-Multiselect>
</div>
</div>
</div>
es ist mir eine freude wenn ich dir helfe
OPTION 1: Verwenden des von Angular bereitgestellten Filterkomparators
// declaring a comparator method
$scope.filterBy = function(actual, expected) {
return _.contains(expected, actual); // uses underscore library contains method
};
var employees = [{name: 'a'}, {name: 'b'}, {name: 'c'}, {name: 'd'}];
// filter employees with name matching with either 'a' or 'c'
var filteredEmployees = $filter('filter')(employees, {name: ['a','c']}, $scope.filterBy);
OPTION 2: Verwenden der von Angular bereitgestellten Filternegation
var employees = [{name: 'a'}, {name: 'b'}, {name: 'c'}, {name: 'd'}];
// filter employees with name matching with either 'a' or 'c'
var filteredEmployees = $filter('filter')($filter('filter')(employees, {name: '!d'}), {name: '!b'});