Voglio usare il filter
in angular e voglio filtrare per più valori, se ha uno dei valori che dovrebbe essere visualizzato.
Ho per esempio questa struttura:
Un movie
object che ha i genres
proprietà e voglio filtrare per Action
e Comedy
.
So che posso fare il filter:({genres: 'Action'} || {genres: 'Comedy'})
, ma cosa fare se voglio filtrarlo dynamicmente. Es. filter: variableX
Come imposto variableX
in $scope
, quando ho una matrice dei generi che devo filtrare?
Potrei costruirlo come una stringa e poi fare un eval()
ma non voglio usare eval () …
Vorrei solo creare un filtro personalizzato. Non sono così difficili.
angular.module('myFilters', []). filter('bygenre', function() { return function(movies,genres) { var out = []; // Filter logic here, adding matches to the out var. return out; } });
Movies
Action
Family
{{genrefilters.action}}::{{genrefilters.family}} - {{movie.title}}: {{movie.genre}}
Modifica qui è il collegamento: Creazione di filtri angolari
AGGIORNAMENTO : Ecco un violino che ha una demo esatta del mio suggerimento.
È ansible utilizzare una funzione controller per filtrare.
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:
- {{ movie.name }} {{ movie.genre }}
La creazione di un filtro personalizzato potrebbe essere eccessivo qui, puoi semplicemente passare in un comparatore personalizzato, se hai valori multipli come:
$scope.selectedGenres = "Action, Drama"; $scope.containsComparator = function(expected, actual){ return actual.indexOf(expected) > -1; };
quindi nel filtro:
filter:{name:selectedGenres}:containsComparator
Ecco l’implementazione del filtro personalizzato, che filtrerà i dati utilizzando una matrice di valori. Supporterà più oggetti chiave con array e valore singolo di chiavi. Come menzionato inangularJS API AngularJS filter Doc supporta più filtri chiave con un singolo valore, ma sotto il filtro personalizzato supporterà la stessa funzionalità di angularJS e supporta anche array di valori e combinazione di array e valore singolo di chiavi.Per trovare lo snippet di codice qui sotto,
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 0){ this.filteredData = fData; } } } }; if (keyObj){ angular.forEach(keyObj,function(obj,key){ filterObj.applyFilter(obj,key); }); } return filterObj.filteredData; } }]);
Uso:
arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
Ecco un esempio di violino con implementazione del filtro personalizzato “filterMutiple” sopra. ::: Fiddle Example :::
Se vuoi filtrare su Array of Objects allora puoi dare
filter:({genres: 'Action', key :value }.
La proprietà individuale verrà filtrata dal filtro specifico fornito per quella proprietà.
Ma se volevi qualcosa come il filtro per singola proprietà e il filtro globale per tutte le proprietà, allora puoi fare qualcosa di simile.
Ci ho dedicato un po ‘di tempo e grazie a @chrismarx ho visto che filterFilter di default di filterFilter
ti consente di passare il tuo comparatore. Ecco il comparatore modificato per più valori:
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; } };
E se vogliamo creare un filtro personalizzato per DRY:
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); }; });
E poi possiamo usarlo ovunque vogliamo:
$scope.list=[ {name:'Jack Bauer'}, {name:'Chuck Norris'}, {name:'Superman'}, {name:'Batman'}, {name:'Spiderman'}, {name:'Hulk'} ]; - {{item.name}}
Finalmente ecco un plunkr .
Nota: l’array previsto dovrebbe contenere solo oggetti semplici come String , Number ecc.
puoi usare il filtro searchField di angular.filter
JS:
$scope.users = [ { first_name: 'Sharon', last_name: 'Melendez' }, { first_name: 'Edmundo', last_name: 'Hepler' }, { first_name: 'Marsha', last_name: 'Letourneau' } ];
HTML:
{{ user.first_name }} {{ user.last_name }}
Puoi anche usare ngIf
se la situazione lo consente:
{{ p.name }} is cool
La soluzione più rapida che ho trovato è quella di utilizzare il filtro dal filtro angular , ad esempio:
- {{movie.name}} ({{movie.genre}}) - {{movie.rating}}
Il lato positivo è che il filtro angular è una libreria abbastanza popolare (~ 2.6k stelle su GitHub) che è ancora triggersmente sviluppata e mantenuta, quindi dovrebbe essere bello aggiungerla al progetto come dipendenza.
Credo che questo sia quello che stai cercando:
{{ (collection | fitler1:args) + (collection | filter2:args) }}
Per favore prova questo
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; } }]);
Supponiamo che tu abbia due array, uno per il film e uno per il genere
Usa semplicemente il filtro come: filter:{genres: genres.type}
Qui i generi sono l’array e il tipo ha un valore per il genere
Ho scritto questo per le stringhe e la funzionalità (so che non è la domanda ma l’ho cercata e sono arrivata qui), forse può essere espansa.
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; }); }; });
Uso:
{{x.name}}
Modulo angular o filtro
$filter('orFilter')([{..}, {..} ...], {arg1, arg2, ...}, false)
ecco il link: https://github.com/webyonet/angular-or-filter
Ho avuto una situazione simile. Scrivere filtri personalizzati ha funzionato per me. Spero che questo ti aiuti!
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:
- {{ movie.name }} {{ movie.genre }}
Ecco il mio esempio come creare filtri e direttive per table jsfiddle
direttiva ottenere lista (dati) e creare tabella con filtri
{{title}}
piacere se ti aiuto
È troppo tardi per partecipare alla festa, ma potrebbe essere utile per qualcuno:
Possiamo farlo in due fasi, prima filtrare prima la proprietà e poi concatenare con il secondo filtro:
$scope.filterd = $filter('filter')($scope.empList, { dept: "account" }); $scope.filterd = $scope.filterd.concat($filter('filter')($scope.empList, { dept: "sales" }));
Guarda il violino funzionante con più filtri di proprietà
La mia soluzione
ng-repeat="movie in movies | filter: {'Action'} + filter: {'Comedy}"
la migliore risposta è:
filter:({genres: 'Action', genres: 'Comedy'}