implementando_o_filtro - VWJavascript/Alurapic GitHub Wiki
Agora que temos tudo encaixado, podemos concluir a lógica do nosso filtro:
// alurapic/client/app/foto/foto.pipes.ts
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'filtroPorTitulo'
})
export class FiltroPorTitulo implements PipeTransform {
transform(fotos, digitado) {
digitado = digitado.toLowerCase();
return fotos.filter( foto => foto.titulo.toLowerCase().includes(digitado));
}
}
Para ficar moderno, estou usando uma arrow function, yeah! Vamos dissecar esse código. Primeiramente, o método transform será chamado toda vez que digitarmos no campo do filtro. Daí, capturamos o que o usuário digitou na variável filtro. Se temos a lista de fotos e o filtro, podemos filtrar a lista retornando apenas as fotos que tenham como título parte do que digitamos. Se filtro possui valor (usuário digitou algo), filtramos a lista pelo valor do filtro, mas se filtro estiver em branco (quando não há valor algum), retornamos a lista de fotos com todos os seus elementos. Escrevemos um código que faz muita coisa com pouquíssimas linhas!
Porém, durante a escrita do nosso código não tivemos o recurso do autocomplete, porque não tipamos o parâmetro do método transform. Vamos fazer isso agora e reescrever a função com auxílio do editor?
// alurapic/client/app/foto/foto.pipes.ts
import { Pipe, PipeTransform } from '@angular/core';
import { FotoComponent } from './foto.component';
@Pipe({
name: 'filtroPorTitulo'
})
export class FiltroPorTitulo implements PipeTransform {
transform(fotos: FotoComponent[], digitado: string) {
digitado = digitado.toLowerCase();
return fotos.filter( foto => foto.titulo.toLowerCase().includes(digitado));
}
}
O primeiro parâmetro agora é um array de FotoComponent e o segundo uma string. Como o primeiro tipo foi criado por nós, precisamos importar sua classe. Como o nosso compilador TypeScript conhece os tipos, pudemos realizar o autocomplete. Porém, o mesmo não foi possível para foto.titulo. Como não tipamos os atributos da classe Foto, o TypeScript não poderá ajudar nosso editor. Que tal realizarmos a tipagem agora?
Inclusive, vamos aproveitar e criar a propriedade descricao que usaremos no próximo capítulo. Contudo, esta propriedade não usará o decorator Input, pois só queremos que o componente receba apenas a URL e o título como parâmetros:
// alurapic/client/app/foto/foto.component.ts
import { Component, Input } from '@angular/core';
@Component({
moduleId: module.id,
selector: 'foto',
templateUrl: './foto.component.html'
})
export class FotoComponent {
@Input() titulo: string;
@Input() url: string;
descricao: string;
}
Elaboramos todo nosso código, mas quando digitamos no campo de filtro a lista de fotos não é filtrada. O que está acontecendo? Os dados estão chegando no filtro e ele parece estar funcionando perfeitamente. Certamente é um problema na atualização da view.
Isso acontece porque Angular só atualizará a view em resposta a um evento assíncrono. Veja, evento! Quando digitamos no campo, não estamos disparando evento algum. Que tal se dispararmos um evento de mentirinha, que nada faz mas que sinalizará para o Angular atualizar a view?
Realizando o truque:
<!-- alurapic/client/app/listagem/listagem.component.html -->
<!-- código anterior omitido -->
<input class="form-control" #textoProcurado (keyup)="0"
placeholder="filtrar pelo título da foto">
<!-- código posterior omitido -->
Veja que estamos envolvendo o atributo keyup entre parênteses, a sintaxe do Angular 2 para associação de eventos, ou no inglês event binding. Toda vez que digitarmos no campo, o evento keyup que nada faz será disparado e mesmo não executando lógica nenhuma, fará com que o Angular atualize nossa view e por conseguinte a nossa lista filtrada.