AngularJS benutzerdefinierte Filterfunktion

91

In meinem Controller möchte ich ein Array von Objekten filtern. Jedes dieser Objekte ist eine Karte, die sowohl Zeichenfolgen als auch Listen enthalten kann

Ich habe versucht, das $filter('filter')(array, function)Format zu verwenden, weiß aber nicht, wie ich auf die einzelnen Elemente des Arrays in meiner Funktion zugreifen soll. Hier ist ein Ausschnitt, um zu zeigen, was ich will.

$filter('filter')(array, function() {
  return criteriaMatch(item, criteria);
});

Und dann criteriaMatch()werde ich in der prüfen, ob jede einzelne Eigenschaft übereinstimmt

var criteriaMatch = function(item, criteria) {
  // go thro each individual property in the item and criteria
  // and check if they are equal
}

Ich muss all dies in der Steuerung tun und eine Liste von Listen zusammenstellen und sie in den Bereich setzen. Ich muss also nur auf $filter('filter')diese Weise darauf zugreifen . Alle Beispiele, die ich bisher im Netz gefunden habe, haben statische Kriteriensuchen innerhalb der Funktion, sie übergeben kein Kriterienobjekt und testen nicht für jedes Element im Array.

user2368436
quelle
3
Warum brauchen Sie einen Filter? Normalerweise werden Filter aus Vorlagen verwendet. Können Sie nicht einfach eine einfache Funktion in Ihrem Controller haben, wenn Sie sie nur von dort aus verwenden?
Ketan
Anstatt jedes Element des Arrays manuell zu durchlaufen, dachte ich, wir könnten die $ filter ('filter') -Funktionalität von angle verwenden (die sich um die Iteration durch jedes Element kümmert, wenn wir nur die Prädikatfunktion angeben)
user2368436

Antworten:

173

Sie können es folgendermaßen verwenden: http://plnkr.co/edit/vtNjEgmpItqxX5fdwtPi?p=preview

Akzeptiert, wie Sie festgestellt haben, filtereine Prädikatfunktion, die Element für Element aus dem Array akzeptiert. Sie müssen also nur eine Prädikatfunktion erstellen, die auf der angegebenen basiert criteria.

In diesem Beispiel criteriaMatchhandelt es sich um eine Funktion, die eine Prädikatfunktion zurückgibt, die der angegebenen entspricht criteria.

Vorlage:

<div ng-repeat="item in items | filter:criteriaMatch(criteria)">
  {{ item }}
</div>

Umfang:

$scope.criteriaMatch = function( criteria ) {
  return function( item ) {
    return item.name === criteria.name;
  };
};
Tosh
quelle
Ich werde diese Kriterien-Match-Funktion nicht aus dem HTML verwenden. Wie werde ich sie aus dem Controller heraus aufrufen? Ist das richtig? $ filter ('filter') (array, function () {RückgabekriterienMatch (Element, Kriterien);});
user2368436
6
Wenn Sie es nicht in Ihrer Vorlage verwenden, bietet das Definieren des Filters keinen Vorteil. Sie können einfach eine einfache Javascript-Funktion definieren, da diese dort noch kürzer ist. Sie können native filterMethode im Array-Objekt verwenden:array.filter(function(item){return item.name === criteria.name;})
Tosh
Ich habe eine Javascript-Funktion. Ich wollte nur sicherstellen, dass Angular keine einfachere Möglichkeit hat. Ich werde Ihre Antwort akzeptieren. Vielen Dank.
user2368436
2

Hier ist ein Beispiel dafür, wie Sie es filterin Ihrem AngularJS-JavaScript verwenden würden (und nicht in einem HTML-Element).

In diesem Beispiel haben wir ein Array von Länderdatensätzen, die jeweils einen Namen und einen dreistelligen ISO-Code enthalten.

Wir möchten eine Funktion schreiben, die diese Liste nach einem Datensatz durchsucht, der einem bestimmten dreistelligen Code entspricht.

So würden wir es machen, ohne zu verwenden filter:

$scope.FindCountryByCode = function (CountryCode) {
    //  Search through an array of Country records for one containing a particular 3-character country-code.
    //  Returns either a record, or NULL, if the country couldn't be found.
    for (var i = 0; i < $scope.CountryList.length; i++) {
        if ($scope.CountryList[i].IsoAlpha3 == CountryCode) {
            return $scope.CountryList[i];
        };
    };
    return null;
};

Ja, daran ist nichts auszusetzen.

Aber so würde dieselbe Funktion aussehen, wenn man Folgendes verwendet filter:

$scope.FindCountryByCode = function (CountryCode) {
    //  Search through an array of Country records for one containing a particular 3-character country-code.
    //  Returns either a record, or NULL, if the country couldn't be found.

    var matches = $scope.CountryList.filter(function (el) { return el.IsoAlpha3 == CountryCode; })

    //  If 'filter' didn't find any matching records, its result will be an array of 0 records.
    if (matches.length == 0)
        return null;

    //  Otherwise, it should've found just one matching record
    return matches[0];
};

Viel ordentlicher.

Denken Sie daran, dass filterals Ergebnis ein Array zurückgegeben wird (eine Liste übereinstimmender Datensätze). In diesem Beispiel möchten wir entweder 1 Datensatz oder NULL zurückgeben.

Hoffe das hilft.

Mike Gledhill
quelle
0

Wenn Sie den Filter in Ihrem Controller auf die gleiche Weise wie hier verwenden möchten:

<div ng-repeat="item in items | filter:criteriaMatch(criteria)">
  {{ item }}
</div>

Sie könnten so etwas tun wie:

var filteredItems =  $scope.$eval('items | filter:filter:criteriaMatch(criteria)');
cafesanu
quelle
6
Alternativvar filteredItems = $filter('criteriaMatch')(items, criteria);
321zeno