it-swarm.com.de

So filtern Sie mehrere Werte (ODER-Verknüpfung) in angleJS

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 ...

128
JustGoscha

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;
    }
  });

vorlage:

<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.

83
Xesued

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>
77
jlareau

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
22
chrismarx

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">
Wobei "filterObject" ein Objekt zum Suchen einer einzelnen Eigenschaft ist und "Search" in jeder Eigenschaft global sucht.

~ Atul

13
user1941574

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.

9
s.alem

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 -->
7
a8m

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.

6
Priidu Neemre

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>
6
cyberwombat

Ich glaube, das ist, wonach Sie suchen:

<div>{{ (collection | fitler1:args) + (collection | filter2:args) }}</div>
4
jKlaus

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

2
Amit Yadav

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;
    }
}]);
2
rajeshpanwar

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>
1
hari nair

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

1
Ali Adravi

Winkel- oder Filtermodul

$filter('orFilter')([{..}, {..} ...], {arg1, arg2, ...}, false)

hier ist der Link: https://github.com/webyonet/angular-or-filter

1
Burak Demirezen

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>
1
Uri

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

1
Jasmin Kurtic

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'});
0
Deepak Acharya