Функция пользовательского фильтра AngularJS

Внутри моего контроллера я хотел бы отфильтровать массив объектов. Каждый из этих объектов представляет собой карту, которая может содержать строки, а также списки

Я пробовал использовать формат $filter('filter')(array, function), но я не знаю, как обращаться к отдельным элементам массива внутри моей функции. Вот фрагмент, чтобы показать, что я хочу.

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

И затем в criteriaMatch(), я проверю, соответствует ли каждое из индивидуального свойства

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

Я должен сделать все это в контроллере и скомпилировать список списков и установить их в области. Поэтому мне нужно получить доступ только к $filter('filter'). Все примеры, которые я нашел в сети до сих пор, имеют статические критерии поиска внутри функции, они не передают объект критериев и не проверяют каждый элемент массива.

Ответ 1

Вы можете использовать его следующим образом: http://plnkr.co/edit/vtNjEgmpItqxX5fdwtPi?p=preview

Как вы нашли, filter принимает функцию предиката, которая принимает элемент по элементу из массива. Итак, вам просто нужно создать функцию предиката, основанную на заданном criteria.

В этом примере criteriaMatch - это функция, которая возвращает предикат функция, которая соответствует заданному criteria.

шаблон:

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

Объем:

$scope.criteriaMatch = function( criteria ) {
  return function( item ) {
    return item.name === criteria.name;
  };
};

Ответ 2

Вот пример того, как вы будете использовать filter в своем JavaScript-коде AngularJS (а не в HTML-элементе).

В этом примере у нас есть массив записей Country, каждый из которых содержит имя и трехзначный код ISO.

Мы хотим написать функцию, которая будет искать в этом списке запись, которая соответствует определенному 3-символьному коду.

Вот как мы это сделаем, не используя 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;
};

Да, ничего страшного в этом.

Но вот как будет выглядеть одна и та же функция, используя 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];
};

Много более аккуратно.

Помните, что filter возвращает массив в результате (список совпадающих записей), поэтому в этом примере мы либо хотим вернуть 1 запись, либо NULL.

Надеюсь, что это поможет.

Ответ 3

Кроме того, если вы хотите использовать фильтр в контроллере так же, как вы это делаете:

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

Вы можете сделать что-то вроде:

var filteredItems =  $scope.$eval('items | filter:filter:criteriaMatch(criteria)');