Je souhaite utiliser la variable filter
dans angular et filtrer plusieurs valeurs. Si l'une de ces valeurs est définie, elle doit être affichée.
J'ai par exemple cette structure:
Un objet movie
qui a la propriété genres
et que je veux filtrer pour Action
et Comedy
.
Je sais que je peux faire filter:({genres: 'Action'} || {genres: 'Comedy'})
, mais que faire si je veux le filtrer de manière dynamique. Par exemple. filter: variableX
Comment définir variableX
dans le $scope
, lorsque j'ai un tableau des genres à filtrer?
Je pourrais le construire en tant que chaîne puis faire une eval()
mais je ne veux pas utiliser eval () ...
Je voudrais juste créer un filtre personnalisé. Ils ne sont pas si durs.
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>
Edit voici le lien: Création de filtres angulaires
UPDATE: Voici un violon qui a une démonstration exacte de ma suggestion.
Vous pouvez utiliser une fonction de contrôleur pour filtrer.
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>
Créer un filtre personnalisé est peut-être excessif ici, vous pouvez simplement passer un comparateur personnalisé, si vous avez des valeurs multiples telles que:
$scope.selectedGenres = "Action, Drama";
$scope.containsComparator = function(expected, actual){
return actual.indexOf(expected) > -1;
};
puis dans le filtre:
filter:{name:selectedGenres}:containsComparator
Voici l’implémentation du filtre personnalisé, qui filtrera les données à l’aide d’un tableau de valeurs. Il prendra en charge plusieurs objets de clé avec un tableau et une valeur unique de clés. Comme mentionné inangularJS API Filtre AngularJS Doc prend en charge le filtre à clés multiples avec une valeur unique, mais sous le filtre personnalisé prendra en charge la même fonctionnalité que angularJS et prend également en charge un tableau de valeurs et une combinaison de valeurs de tableau et de valeurs uniques. Veuillez trouver le code extrait ci-dessous,
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;
}
}]);
Utilisation:
arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
Voici un exemple de violon avec la mise en œuvre de "filterMutiple" filtre personnalisé . ::: Exemple de violon :::
Si vous souhaitez filtrer sur un tableau d'objets, vous pouvez donner
filter:({genres: 'Action', key :value }.
Une propriété individuelle sera filtrée par un filtre particulier donné pour cette propriété.
Mais si vous souhaitez utiliser quelque chose comme filtrer par propriété individuelle et filtrer globalement pour toutes les propriétés, vous pouvez procéder de la sorte.
<tr ng-repeat="supp in $data | filter : filterObject | filter : search">
~ Atul
J'ai passé un peu de temps dessus et grâce à @chrismarx, j'ai vu que la variable par défaut angular filterFilter
vous permet de passer votre propre comparateur. Voici le comparateur édité pour plusieurs valeurs:
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;
}
};
Et si nous voulons créer un filtre personnalisé pour 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);
};
});
Et ensuite, nous pouvons l'utiliser n'importe où:
$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>
Enfin, voici un plunkr .
Remarque: le tableau attendu ne doit contenir que des objets simples tels que String, Number etc.
vous pouvez utiliser le filtre searchField de angular.filter
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 -->
La solution la plus rapide que j'ai trouvée consiste à utiliser le filtre filterBy
de angular-filter , par exemple:
<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>
L’avantage, c’est que angular-filter est une bibliothèque assez populaire (environ 2,6 000 étoiles sur GitHub), qui est toujours activement développée et maintenue. Il est donc conseillé de l’ajouter à votre projet en tant que dépendance.
Vous pouvez également utiliser ngIf
si la situation le permet:
<div ng-repeat="p in [
{ name: 'Justin' },
{ name: 'Jimi' },
{ name: 'Bob' }
]" ng-if="['Jimi', 'Bob'].indexOf(e.name) > -1">
{{ p.name }} is cool
</div>
Je crois que c'est ce que vous cherchez:
<div>{{ (collection | fitler1:args) + (collection | filter2:args) }}</div>
Supposons que vous avez deux tableaux, un pour le film et un pour le genre.
Utilisez simplement le filtre en tant que: filter:{genres: genres.type}
Ici, les genres étant le tableau et le type a une valeur pour le genre
S'il vous plaît essayez ceci
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;
}
}]);
J'ai eu la même situation. L'écriture d'un filtre personnalisé a fonctionné pour moi. J'espère que cela t'aides!
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>
Trop tard pour rejoindre le parti mais peut-être peut-il aider quelqu'un:
Nous pouvons le faire en deux étapes, d’abord filtrer par la première propriété puis concaténer par le deuxième filtre:
$scope.filterd = $filter('filter')($scope.empList, { dept: "account" });
$scope.filterd = $scope.filterd.concat($filter('filter')($scope.empList, { dept: "sales" }));
Voir le violon en marche avec filtre de propriétés multiples
J'ai écrit ceci pour les chaînes ET les fonctionnalités (je sais que ce n'est pas la question, mais je l'ai recherchée et je suis arrivé ici), peut-être qu'il peut être développé.
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;
});
};
});
Usage:
<li ng-repeat="x in array | filterMultiple:{key1: value1, key2:[value21, value22]}">{{x.name}}</li>
Voici mon exemple comment create filter et directive for table jsfiddle
directive get list (datas) et crée une table avec des filtres
<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>
mon plaisir si je vous aide
OPTION 1: Utilisation du paramètre comparateur de filtre fournisseur angulaire
// 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: Utilisation de la négation de filtre fournisseur angulaire
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'});