Wie filtere ich ein Array mit AngularJS und verwende eine Eigenschaft des gefilterten Objekts als ng-model-Attribut?

121

Wie mache ich das, wenn ich ein Array von Objekten habe und das Angular-Modell an eine Eigenschaft eines der Elemente binden möchte, die auf einem Filter basieren? Ich kann es anhand eines konkreten Beispiels besser erklären:

HTML:

<!DOCTYPE html>
<html ng-app>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
        <meta charset=utf-8 />
        <title>JS Bin</title>
    </head>
    <body ng-controller="MyCtrl">
        <input ng-model="results.year">
        <input ng-model="results.subjects.title | filter:{grade:'C'}">
    </body>
</html>

Regler:

function MyCtrl($scope) {
  $scope.results = {
    year:2013,
    subjects:[
      {title:'English',grade:'A'},
      {title:'Maths',grade:'A'},
      {title:'Science',grade:'B'},
      {title:'Geography',grade:'C'}
    ]
  };
}

JSBin: http://jsbin.com/adisax/1/edit

Ich möchte die zweite Eingabe für das Thema mit der Note 'C' filtern, aber ich möchte das Modell nicht an die Note binden . Ich möchte es an den Titel des Fachs mit der Note "C" binden .

Ist das möglich und wenn ja, wie wird es gemacht?

Bernhard Hofmann
quelle

Antworten:

127
<div ng-repeat="subject in results.subjects | filter:{grade:'C'}">
    <input ng-model="subject.title" />
</div>
JB Nizet
quelle
1
Ich sehe, wohin du damit gehst, aber ich wollte wirklich keinen Repeater. Die Eigenschaft, nach der ich tatsächlich filtern werde, ist eine Identitätsspalte, daher ist sie eindeutig. Aber ich sehe, dass dies der richtige Weg wäre, um das generische Problem zu lösen.
Bernhard Hofmann
1
Dies ist ein Tutorial für Italiener
Silvio Troia
10
Dies war sehr hilfreich, und für inverse (alles andere als C) würde dies funktionieren:filter:{grade:'!'+'C'}
pulkitsinghal
2
Kannst du dasselbe mit einem machen grade array? In meinem Fall erstelle ich mein Notenarray aus einer Baumansicht und möchte das Ergebnis nach denen im Array filtern.
Juan Carlos Oropeza
157

Sie können den Filter "Filter" in Ihrem Controller verwenden, um alle Noten "C" zu erhalten. Wenn Sie das erste Element des Ergebnisarrays abrufen, erhalten Sie den Titel des Fachs mit der Note "C".

$scope.gradeC = $filter('filter')($scope.results.subjects, {grade: 'C'})[0];

http://jsbin.com/ewitun/1/edit

Das gleiche gilt für einfaches ES6:

$scope.gradeC = $scope.results.subjects.filter((subject) => subject.grade === 'C')[0]
Oliver
quelle
Es tut mir leid, dass ich diesem zweiten Filter ('Filter') nicht folge. Können Sie diesen etwas näher erläutern?
Winnemucca
1
@stevek Das ist der Name des Filters. Die filter () -Methode gibt Ihnen den Filter. Es ist nur so, dass Filter Filter genannt wird, weil er ein Array filtert. Mit dem Währungsfilter würde es so aussehen: $ filter ('Währung') (Betrag, Symbol, Bruchgröße
Oliver
61

Hier ist ein modifizierter JSBin mit einem Arbeitsbeispiel:

http://jsbin.com/sezamuja/1/edit

Folgendes habe ich mit Filtern in der Eingabe gemacht:

<input ng-model="(results.subjects | filter:{grade:'C'})[0].title">
lukeatdesignworks
quelle
1
Das ist der wahre Deal. Das ist die Kraft. Das ist der Weg. Ich ging damit und jetzt bin ich glücklich.
user1576978
13

Bitte beachten Sie, wenn Sie $ filter wie folgt verwenden:

$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});

und du hattest zufällig eine andere Note für Oh, ich weiß nicht, CC oder AC oder C + oder CCC, in die sie hineingezogen werden. Sie müssen eine Anforderung für eine genaue Übereinstimmung anhängen:

$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'}, true);

Das hat mich wirklich umgebracht, als ich einige Provisionsdetails wie diese eingeholt habe:

var obj = this.$filter('filter')(this.CommissionTypes, { commission_type_id: 6}))[0];

Lassen Sie sich nur wegen eines Fehlers anrufen, weil die Provisions-ID 56 statt 6 eingegeben wurde.

Durch Hinzufügen der wahren Kräfte wird eine exakte Übereinstimmung erzielt.

var obj = this.$filter('filter')(this.CommissionTypes, { commission_type_id: 6}, true))[0];

Trotzdem bevorzuge ich dies (ich verwende Typoskript, daher das "Let" und =>):

let obj = this.$filter('filter')(this.CommissionTypes, (item) =>{ 
             return item.commission_type_id === 6;
           })[0];

Ich mache das, weil ich irgendwann auf der Straße vielleicht mehr Informationen über diese gefilterten Daten usw. erhalten möchte. Wenn die Funktion genau dort drin ist, bleibt die Motorhaube offen.

Daniel Morris
quelle
Ich hatte den gleichen Fehler wie Sie, danke für den Hinweis mit dem dritten booleschen Parameter. War sich dessen nicht bewusst.
Georg Leber
12

Wenn Sie eine separate Ergebnisliste im Controller erstellen möchten, können Sie einen Filter anwenden

function MyCtrl($scope, filterFilter) {
  $scope.results = {
    year:2013,
    subjects:[
      {title:'English',grade:'A'},
      {title:'Maths',grade:'A'},
      {title:'Science',grade:'B'},
      {title:'Geography',grade:'C'}
    ]
  };
  //create a filtered array of results 
  //with grade 'C' or subjects that have been failed
  $scope.failedSubjects = filterFilter($scope.results.subjects, {'grade':'C'});
}

Dann können Sie verweisen failedSubjects auf die gleiche Weise die Referenz würde Ergebnisse Objekt

Sie können hier mehr darüber lesen https://docs.angularjs.org/guide/filter

Da diese Antwort eckig die Dokumentation aktualisiert hat, empfehlen sie nun, den Filter aufzurufen

// update 
// eg: $filter('filter')(array, expression, comparator, anyPropertyKey);
// becomes
$scope.failedSubjects = $filter('filter')($scope.results.subjects, {'grade':'C'});
Kieran
quelle
Was ist FilterFilter? Ist es ein Dienst oder eine Richtlinie? Wo ist der Code für filterFilter?
Mou
Es ist ein eckiger Service. Schauen Sie sich das erste Beispiel im obigen Link an. (in der Datei scripts.js)
Kieran
obwohl sie die Dokumentation geändert haben filterFilter funktioniert immer noch ..
Kieran
4

Sie können Funktionen auch verwenden mit : $filter('filter')

var foo = $filter('filter')($scope.results.subjects, function (item) {
  return item.grade !== 'A';
});
Nelu
quelle
4

Wenn Sie ES6 verwenden, können Sie:

var sample = [1, 2, 3]

var result = sample.filter(elem => elem !== 2)

/* output */
[1, 3]

Beachten Sie auch, dass der Filter das vorhandene Array nicht aktualisiert und jedes Mal ein neues gefiltertes Array zurückgibt.

Diego Venâncio
quelle
0

Anwenden des gleichen Filters in HTML mit mehreren Spalten, nur Beispiel:

 variable = (array | filter : {Lookup1Id : subject.Lookup1Id, Lookup2Id : subject.Lookup2Id} : true)
Amay Kulkarni
quelle