Fala galera, beleza?

Já precisou formatar algum dado para exibir para o usuário? Pensou em fazer o tratamento lá no backend ou criar uma função javascript para fazer o parse e exibir? Então, neste post vamos ver como o AngularJS trata essa questão com os filters.

Filtro

Os filtros são utilizados para fazer a formatação dos dados e exibi-los ao usuário. Uma definição bem simples, igual correr com medo dos caretas na Semana Santa lá no meu Brejim (quem é do interior cearense sabe do que eu estou falando!).

O AngularJS já possui alguns filtros padrão, como, por exemplo, currency para formatação de moeda e date para formatação de datas. Na API de Referência podemos verificar todos os filtros disponibilizados pelo framework.

Os filtros podem ser usados na view, no controller, na directive ou no service. Nós podemos também criar de maneira muito fácil o nosso próprio filtro.

Veja os exemplos abaixo:

Usando filtros na view

Para utilizarmos o filter na view usamos o | (pipe) dentro da expressão {{}}, por exemplo: meu salário {{ 123456789 | currency }}, que vai dar $123,456,789.00 como resposta.

Os filtros podem ser utilizados encadeados, ou seja, o resultado de um pode servir de entrada para o outro, exemplo: {{ “1984-12-15T00:00” | date | uppercase }}, que teria como saída DEC 15, 1984.

Eles ainda podem receber parâmetros, como {{ “1984-12-15T00:00” | date: ‘medium’ }} e sua respectiva saída Dec 15, 1984 12:00:00 AM.

Os exemplos acima  podem ser vistos no gist abaixo e/ou rodando aqui.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html ng-app="app-filters">

<head>
    <meta charset="UTF-8">
    <title>Blog do Gabriel Feitosa > AngularJS: Filtros</title>
</head>

<body>
    <h1>Filtros - Na View</h1>
    <pre>Filtro currency {{123456789 | currency}} = {{ 123456789 | currency}}</pre>
    <pre>Filtro encadeados {{"1984-12-15T00:00" | date | uppercase}} = {{ "1984-12-15T00:00" | date | uppercase}}</pre>
    <pre>Filtro date com parâmetro {{"1984-12-15T00:00" | date}} = {{ "1984-12-15T00:00" | date:'medium'}}</pre>
    <footer>
        <hr/>
        <a href="http://www.gabrielfeitosa.com"> Blog do Gabriel Feitosa</a>
    </footer>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
    <script src="app.js"></script>
</body>
</html>

Nota: Para que o AngularJS funcione com a formatação local para currency, number date precisaríamos adicionar a internacionalização.

Usando filtros no controller, service e/ou directive

Filtros também podem ser utilizados em controladores, serviços e diretivas. Para isso, precisamos do controle de injeção de dependência.

Há duas maneiras de um filtro ser injetado, aqui você pode ver o gist do html e aqui você o vê rodando:

1
2
3
4
5
6
7
8
9
10
11
(function() {
  'use strict';

  angular.module('app-filters')
    .controller('ExemploController', function($scope, $filter,currencyFilter) {
      $scope.moedaFormatada = $filter('currency')(123456789);
      $scope.moedaFormatada2 = currencyFilter(123456789);
      $scope.dataFormatada = $filter('date')('1984-12-15T00:00','medium');
    });

})();
  1. Adicionar o sufixo Filter ao nome do filtro **Filter**. Por exemplo, **currencyFilter;**
  2. Injetar o service $filter e passar, como parâmetro, qual filtro desejamos utilizar. Exemplo: $filter(‘date’)(‘1984-12-15T00:00′,’medium’);

Dica de Performance: Utilizar filtros fora da view é uma excelente prática quando temos uma grande quantidade de dados a serem filtrados. Isso fará com que eles não precisem ser reformatados sempre que houver uma atualização na tela. Fora da view, o filtro só é utilizado quando necessário, como quando acontece uma atualização de dados do backend ou quando a expressão do filtro é alterada.

Porquê o sufixo Filter?  O sufixo Filter diz ao sistema de injeção de dependência que, caso o filtro esteja presente no provider, deve utilizá-lo. Caso contrário, o DI retira o sufixo Filter e tenta injetar um filtro com nome correspondente. Assim, se o nome do seu filtro é inverterStringFilter (você nunca deve nomear seus filtros com o sufixo Filter), o DI vai procurar primeiro por inverterStringFilterProvider e, se encontrá-lo, irá usá-lo. Do contrário, ele tenta injetar o filtro de nome inverterString.

Criando filtros customizados

Criar nosso próprio filtro é muito fácil, só precisamos registrá-lo utilizando a function filter no módulo do AngularJS. A syntax pode ser vista no gist abaixo. O primeiro argumento é o nome do filtro e o segundo é a factory function para o filtro.

Vamos criar dois filtros de exemplos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
(function() {
  'use strict';
  angular.module('app-filters', []);

  angular.module('app-filters').filter('cpf', function() {
    return function(input) {
      var str = input + '';
      if(str.length <= 11){
        str = str.replace(/\D/g, '');
        str = str.replace(/(\d{3})(\d)/, "$1.$2");
        str = str.replace(/(\d{3})(\d)/, "$1.$2");
        str = str.replace(/(\d{3})(\d{1,2})$/, "$1-$2");
      }
      return str;
    };
  });

  angular.module('app-filters')
    .filter('abestado', function() {
      return function(input,muito) {
        
        var str = input || ''
        if (input) {
          str += ' é abestado';
          if(muito){
            str += ' de cum força'
          }
        }
        return str;
      };
    });
})();

O filtro de formatação de CPF recebe um único parâmetro de entrada e dá como saída um CPF formatado no formato xxx.xxx.xxx-xx. A syntax para utilização é {{inputCPF | cpf}}, como pode ser visto na linha 13 do gist abaixo.

O segundo filtro que criamos é o abestado. Muito útil para elogiar um grande amigo, ele recebe dois parâmetros de entrada. O primeiro é o nome do amigo e o segundo é se ele é muito abestado ou não. A syntax para utilização é {{nomeDoAmigo | abestado: param1}}, como pode ser visto na linha 16 do gist abaixo. Aqui você pode ver o exemplo rodando.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html ng-app="app-filters">

<head>
    <meta charset="UTF-8">
    <title>Blog do Gabriel Feitosa > AngularJS: Filtros</title>
</head>

<body>
    <h1>Filtros - Customizado</h1>
    <input placeholder="Informe um CPF" ng-model="inputCPF"/>
    {{inputCPF | cpf}}
    <br><br>
    <input placeholder="Nome do amigão do peito?" ng-model="amigo"/> 
    {{ amigo | abestado:muito}}
    <br>
    <input type="checkbox" ng-model="muito"/> Seu amigo é muito abestado?
    <footer>
        <hr/>
        <a href="http://www.gabrielfeitosa.com"> Blog do Gabriel Feitosa</a>
    </footer>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
    <script src="app.js"></script>
</body>
</html>

Filtros nos dão um excelente poder quando o assunto é formatação de dados. Ainda há muitas outras opções que não abordei aqui, como o limitTo e orderBy, que podemos utilizar para limitar e ordenar dados de um coleção de objetos.

Então é isso pessoal, espero que tenham curtido o post.

Abraços e até a próxima!