Função de filtro personalizado AngularJS

91

Dentro do meu controlador, gostaria de filtrar uma série de objetos. Cada um desses objetos é um mapa que pode conter strings, bem como listas

Tentei usar o $filter('filter')(array, function)formato, mas não sei como acessar os elementos individuais do array dentro da minha função. Aqui está um trecho para mostrar o que eu quero.

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

Em seguida criteriaMatch(), verificarei se cada uma das propriedades individuais corresponde

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

Tenho que fazer tudo isso no controlador e compilar uma lista de listas e defini-las no escopo. Portanto, preciso acessar $filter('filter')apenas desta forma. Todos os exemplos que encontrei na rede até agora têm pesquisas de critérios estáticos dentro da função, eles não passam um objeto de critério e testam contra cada item do array.

user2368436
fonte
3
Por que você precisa de um filtro? Normalmente, os filtros são usados ​​a partir de modelos. Você não pode simplesmente ter uma função simples em seu controlador se estiver usando-a apenas a partir daí?
Ketan
em vez de ir manualmente através de cada elemento do array, pensei que poderíamos usar a funcionalidade $ filter ('filter') do angular (que cuidará da iteração de cada elemento se apenas especificarmos a função de predicado)
user2368436

Respostas:

173

Você pode usá-lo assim: http://plnkr.co/edit/vtNjEgmpItqxX5fdwtPi?p=preview

Como você descobriu, filteraceita a função de predicado que aceita item por item do array. Então, você só precisa criar uma função de predicado baseada no dado criteria.

Neste exemplo, criteriaMatché uma função que retorna uma função de predicado que corresponde ao dado criteria.

modelo:

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

escopo:

$scope.criteriaMatch = function( criteria ) {
  return function( item ) {
    return item.name === criteria.name;
  };
};
Tosh
fonte
Não estarei usando essa função criteriaMatch do html .. como vou chamá-la de dentro do controlador está correto? $ filter ('filtro') (matriz, função () {critérios de retornoMatch (item, critérios);});
user2368436
6
Se você não o estiver usando em seu modelo, definir o filtro não oferece nenhuma vantagem. Você pode simplesmente definir uma função javascript simples, já que é ainda mais curta lá. Você pode usar o filtermétodo nativo no objeto Array:array.filter(function(item){return item.name === criteria.name;})
Tosh
Eu tenho uma função javascript. só queria ter certeza de que o angular não teria uma maneira mais fácil de fazer isso .. aceitarei sua resposta. THX.
user2368436
2

Aqui está um exemplo de como você usaria filterem seu JavaScript AngularJS (em vez de em um elemento HTML).

Neste exemplo, temos uma matriz de registros de país, cada um contendo um nome e um código ISO de 3 caracteres.

Queremos escrever uma função que irá pesquisar nesta lista por um registro que corresponda a um código específico de 3 caracteres.

Veja como faríamos isso sem usar 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;
};

Sim, nada de errado com isso.

Mas aqui está como a mesma função ficaria, usando 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];
};

Muito mais puro.

Lembre-se de que filterretorna uma matriz como resultado (uma lista de registros correspondentes), portanto, neste exemplo, queremos retornar 1 registro ou NULL.

Espero que isto ajude.

Mike Gledhill
fonte
0

Além disso, se você quiser usar o filtro em seu controlador da mesma forma que faria aqui:

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

Você poderia fazer algo como:

var filteredItems =  $scope.$eval('items | filter:filter:criteriaMatch(criteria)');
cafesanu
fonte
6
Alternativamente,var filteredItems = $filter('criteriaMatch')(items, criteria);
321zeno 01 de