criando_pipes - VWJavascript/Alurapic GitHub Wiki

Criando nossos pipes

Vamos criar um novo arquivo que guarda a lógica do nosso filtro, mas em qual pasta da nossa aplicação? Como esse filtro só faz sentido ser aplicado em uma lista de Fotos vamos criá-lo dentro da pasta alurapic/client/app/foto/foto.pipes.ts.

// alurapic/client/app/foto/foto.pipes.ts

import {Pipe} from '@angular/core';
@Pipe({
    name: 'filtroPorTitulo'
})
export class FiltroPorTitulo {

    // o correto é transform, eu errei aqui intencionalmente para mostrar algo a seguir!

    transforma(fotos, digitado) {
        console.log(fotos); // quem deve ser filtrado
        console.log(digitado); // o que deve ser usado como filtro
    }
}

A função transform recebe a lista de fotos que desejamos filtrar e como segundo parâmetro o critério do filtro. Ainda não implementamos nossa função totalmente, estamos apenas exibindo os dados via console para entendermos os parâmetros da função.

Agora, precisamos declarar nosso FiltroPorTitulo como fazendo parte do módulo FotoModule. Inclusive, se quisermos que outros módulos tenham acesso ao nosso pipe também precisamos adicioná-la no array de exports:

// alurapic/client/app/foto/foto.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FotoComponent } from './foto.component';
import { FiltroPorTitulo } from './foto.pipes';

@NgModule({
  imports: [ CommonModule ],
  declarations: [ FotoComponent, FiltroPorTitulo ],
  exports: [FotoComponent, FiltroPorTitulo]
})
export class FotoModule { }

Vamos testar? E... Ops! Nossa lista não é mais exibida. O problema é que todo pipe criado por nós deve ter o método transform. Será que eu escrevi errado? Pois é, eu escrevi transforma. Vamos corrigir.

// alurapic/client/app/foto/foto.pipes.ts

import { Pipe } from '@angular/core';
@Pipe({
    name: 'filtroPorTitulo'
})
export class FiltroPorTitulo {
    // o correto é transform
    transform(fotos, digitado) {
        console.log(fotos); // quem deve ser filtrado
        console.log(digitado); // o que deve ser usado como filtro
    }
}

Excelente, apesar da nossa lista de fotos ainda não ser exibida, não recebemos mais a mensagem de erro, inclusive conseguimos ver no console do browser as informações enviamos. Contudo, o problema que tivemos antes, o de termos escrito o nome do método errado é muito grave: só descobrimos um bug em nosso código depois dele estar rodando. Bem que o TypeScript podia nos avisar desse erro em seu terminal, dessa forma, poderíamos corrigir o erro a tempo.

As coisas não se encaixam? Que tal um interface type?

O problema é que o TypeScript não sabe que a classe do nosso Pipe deve implementar o método transform, muito menos que este método deve receber dois parâmetros. Quem dera que pudéssemos chegar para nossa classe e dizer: "olha classe, você é obrigada a ter o método transform, caso contrário o compilador do TypeScript não vai compilá-la". Surpresa! Isso é possível, vejamos o código:

// alurapic/client/app/foto/foto.pipes.ts

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
    name: 'filtroPorTitulo'
})
export class FiltroPorTitulo implements PipeTransform {

    transform(fotos, digitado) {
        console.log(fotos); // quem deve ser filtrado
        console.log(digitado); // o que deve ser usado como filtro   
    }
}

Importamos em nosso código a interface PipeTransform, inclusive fizemos com que nossa classe implemente essa interface. Uma interface no TypeScript é um arquivo que indica as obrigações (contratos) que uma classe deve ter. Na definição da interface PipeTransform, criada pela equipe do Angular, toda classe que assinar esse contrato, isto é, que implemente esta interface, obrigatoriamente deve ter o método transform, caso contrário o TypeScript não compilará o arquivo e exibirá no seu console que ferimos essa obrigatoriedade (quebra de um contrato).

Vamos alterar o nome do método para tranforma novamente:

// alurapic/client/app/foto/foto.pipes.ts

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
    name: 'filtroPorTitulo'
})
export class FiltroPorTitulo implements PipeTransform {

    // voltando a usar a forma incorreta! TypeScript vai reclamar!
    transforma(fotos, digitado) {
        console.log(fotos); // quem deve ser filtrado
        console.log(digitado); // o que deve ser usado como filtro
    }
}

Quando salvarmos nosso arquivo, será exibida a seguinte mensagem o console do TypeScript:

client/app/foto/pipes/filtro-por-titulo.ts(5,14): error TS2420: Class 'FiltroPorTitulo' incorrectly implements interface 'PipeTransform'.
  Property 'transform' is missing in type 'FiltroPorTitulo'.

Perfeito! O TypeScript está nos informando que nossa classe FiltroPorTitulo incorretamente implementa PipeTransform e que transform está faltando. Vamos corrigir nosso método e tipar todos os seus parâmetros, inclusive o retorno:

// alurapic/client/app/foto/foto.pipes.ts

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
    name: 'filtroPorTitulo'
})
export class FiltroPorTitulo implements PipeTransform {

   // tipando todos os parâmetros, inclusive o retorno
    transform(fotos: any, digitado: string): any {

        console.log(fotos); // quem deve ser filtrado
        console.log(digitado); // o que deve ser usado como filtro   
    }
}