2013-03-16 3 views
20

Also, wenn ich ein Array haben:Ist es möglich angular.js durch Eindämmung in einem anderen Array zu filtern?

$scope.letters = 
[{"id":"a"}, 
{"id":"b"}, 
{"id":"c"}]; 

Und ein weiteres Array

$scope.filterBy = ["b","c","d"]; 

Und ich möchte einige ng-repeat filtern scope.letters nur Artikel $ haben, die in $ filterBy erscheinen.

Ich möchte etwas auf die Wirkung der Lage sein, zu tun:

<span ng-repeat="{{letter in letters|filter: letter.id in filterBy }} > {{letter.id}} </span> 

Und es haben drucken b, c

Ich weiß, dass dies ein wirklich dummes Beispiel, aber ist es eine Möglichkeit, einen angular.js-Ausdruck basierend auf dem Inhalt eines anderen Array-Objekts filtern?

Antwort

29

Sie sollten so etwas versuchen:

JS:

angular.module('Test', []); 

function Ctrl($scope) { 
    $scope.letters = [ 
    {id: 'a'}, 
    {id: 'b'}, 
    {id: 'c'} 
    ]; 

    $scope.filterBy = ['b', 'c', 'd']; 

    $scope.filteredLetters = function() { 
    return $scope.letters.filter(function (letter) { 
     return $scope.filterBy.indexOf(letter.id) !== -1; 
    }); 
    }; 
} 

Ctrl.$inject = ['$scope']; 

HTML:

<div ng-repeat='letter in filteredLetters(letters)'>{{letter.id}}</div> 

Sie live example versuchen.

+6

filteredLetters() wird _every_ digest cycle aufgerufen. Also, wenn Sie in Eingabefeld mit ng-Modell in Ihrer Ansicht haben, bedeutet dies jeden Tastendruck. Es wäre besser, die Ergebnisse des Filters auf einer neuen $ scope-Eigenschaft zu speichern. Verwenden Sie $ watch() es, um die Filterergebnisse zu aktualisieren, wenn sich 'letters' oder' filterBy' ändern. –

+0

Guter Punkt. Danke für den Rat. – ValeriiVasin

+0

Während es funktioniert (vorausgesetzt, Ihre App ist sehr einfach) würde ich nicht empfehlen, diesen Ansatz zu verwenden - wie @MarkRajcok erwähnt, es heißt jeder Digest-Zyklus bedeutet Leistung ist schrecklich und ich bekam Fehler von eckigen ähnlich wie "Error: [$ rootScope: infdig] 10 $ digest() Iterationen erreicht. Abbrechen! " –

35

aktualisiert

Hier ist ein Winkelmodul (basierend auf @InviS Antwort) auf einfache Weise diese Filter in Ihrem Winkel Anwendung zu implementieren: filters-inArrayFilter


Hier ist die Winkel Filter auf @InviS Ansatz antwort:

Der Filter sollte wie folgt aussehen:

.filter('inArray', function($filter){ 
    return function(list, arrayFilter, element){ 
     if(arrayFilter){ 
      return $filter("filter")(list, function(listItem){ 
       return arrayFilter.indexOf(listItem[element]) != -1; 
      }); 
     } 
    }; 
}); 

wo Liste die Liste Sie Filterung (diese param standardmäßig durch Winkel eingestellt ist), arrayFilter ist das Array man als Filter verwenden, und Element ist der Name der Eigenschaft, die in Ihrer Liste gefiltert werden soll.

diesen Filter verwenden Sie Ihre ng-repeat wie verwenden:

<div ng-repeat='letter in letters | inArray:filterBy:"id"'>{{letter.id}}</div> 

wo InArray der Filter, filterBy(das erste Argument dieses Filters) ist Ihr Array zu entsprechen, und "ID"(zweites Argument) ist das Elem ent der Liste, die Sie mit dem Array abgleichen möchten.

Sie können dies live example mit dem Winkelfilter Ansatz versuchen.

+0

Was passiert, wenn ich mehrere Spalten filtern muss? Würde 'Verkettung' tun? – dreamer

+0

@dreamer Was meinen Sie mit mehreren Spalten? – Cyberdelphos

+0

@ Cyberdephos Wie würdest du filtern, wenn der Objektschlüssel eine Nummer wäre? benutze $ index? – alphapilgrim

6

Ziemlich alt, aber ich brauchte es und ich musste es ein wenig ändern. Hier ist mein Filter "notInArray"

app.filter('notInArray', function($filter){ 
return function(list, arrayFilter, element){ 
    if(arrayFilter){ 
     return $filter("filter")(list, function(listItem){ 
      for (var i = 0; i < arrayFilter.length; i++) { 
       if (arrayFilter[i][element] == listItem[element]) 
        return false; 
      } 
      return true; 
     }); 
    } 
}; 

});

<md-chips ng-model="filter.SelectedValues" md-autocomplete-snap 
      md-require-match="true"> 
     <md-autocomplete 
      md-search-text="searchFilterChip" 
      md-items="val in filter.Values | notInArray:filter.SelectedValues:'Id'" 
      md-item-text="val.Name" 
      md-no-cache="true" 
      md-min-length="0"> 
     <span md-highlight-text="searchFilterChip">{{val.Name}}</span> 
     </md-autocomplete> 
     <md-chip-template> 
     {{$chip.Name}} 
     </md-chip-template> 
    </md-chips> 

Ich vermute, das kann verbessert werden, aber in meinem Fall nicht benötigt.

Hoffe, dass jemand hilft!

+0

vielen Dank – Magico

Verwandte Themen