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

91

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

Я пробовал использовать $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')этим способом. Все примеры, которые я нашел в сети, имеют статический поиск критериев внутри функции, они не передают объект критериев и не проверяют каждый элемент в массиве.

user2368436
источник
3
Зачем нужен фильтр? Обычно используются фильтры из шаблонов. Разве вы не можете просто использовать в своем контроллере простую функцию, если вы используете ее только оттуда?
Кетан
вместо того, чтобы вручную перебирать каждый элемент массива, я подумал, что мы могли бы использовать функцию $ filter ('filter') angular (которая позаботится об итерации по каждому элементу, если мы просто укажем функцию предиката)
user2368436

Ответы:

174

Вы можете использовать это так: 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;
  };
};
Тош
источник
Я не буду использовать эту функцию критериев соответствия из html .. как мне вызвать ее изнутри контроллера, это правильно? $ filter ('фильтр') (массив, функция () {return условиеMatch (элемент, критерии);});
user2368436
6
Если вы не используете его в своем шаблоне, определение фильтра не даст вам никаких преимуществ. Вы можете просто определить простую функцию javascript, так как она там еще короче. Вы можете использовать собственный filterметод в объекте Array:array.filter(function(item){return item.name === criteria.name;})
Тош,
У меня есть функция javascript. просто хотел убедиться, что у angular нет более простого способа сделать это ... я приму ваш ответ. Спасибо.
user2368436
2

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

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

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

Вот как это сделать без использования 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.

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

Майк Гледхилл
источник
0

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

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

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

var filteredItems =  $scope.$eval('items | filter:filter:criteriaMatch(criteria)');
Cafeesanu
источник
6
В качестве альтернативыvar filteredItems = $filter('criteriaMatch')(items, criteria);
321zeno 01