Criando Pipes Personalizados em Angular
Quando precisamos realizar algum tipo de pré-processamento ou formatação adicional na exibição de dados, podemos criar nossos próprios pipes para essa finalidade.
Os pipes em Angular são definidos como classes que devem implementar a interface PipeTransform:
interface PipeTransform {
transform(value: any, ...args: any[]): any;
}O método transform tem a responsabilidade de transformar o valor de entrada. Ele recebe como parâmetro o valor ao qual o pipe será aplicado, além de um conjunto opcional de parâmetros adicionais. O método retorna o valor formatado. Como o primeiro parâmetro é do tipo any e o segundo é um array do tipo any, podemos trabalhar com dados de qualquer tipo e retornar objetos de qualquer tipo também.
Exemplo Simples
Vamos considerar um exemplo básico. Suponha que desejamos exibir um número onde o separador entre a parte inteira e a parte decimal seja uma vírgula em vez de um ponto. Para isso, podemos criar um pipe simples. Adicionaremos um novo arquivo chamado format.pipe.ts na pasta src/app do nosso projeto:
helloapp/ ├── src/ │ ├── app/ │ │ ├── about.component.ts │ │ ├── format.pipe.ts │ ├── index.html │ ├── main.ts ├── angular.json ├── package-lock.json ├── package.json └── tsconfig.json
Definiremos o seguinte código no arquivo format.pipe.ts:
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
name: "format",
standalone: true,
})
export class FormatPipe implements PipeTransform {
transform(value: number, args?: any): string {
return value.toString().replace(".", ",");
}
}Esse pipe personalizado utiliza o decorador @Pipe, que define metadados, incluindo o nome do pipe que será utilizado no código:
@Pipe({
name: "format",
standalone: true
})Além disso, para permitir que o pipe seja importado em componentes autônomos, ele também é definido como autônomo (standalone).
Aplicando o FormatPipe
Agora, vamos usar o FormatPipe dentro de um componente:
import { Component } from "@angular/core";
import { FormatPipe } from "./format.pipe";
@Component({
selector: "my-app",
standalone: true,
imports: [FormatPipe],
template: `<div>Número antes da formatação: {{ x }}<br />Número depois da formatação: {{ x | format }}</div>`,
})
export class AppComponent {
x: number = 15.45;
}Esse código irá exibir o número formatado, substituindo o ponto decimal por uma vírgula.

Passando Parâmetros para Pipes
Agora, vamos criar um outro pipe que aceite parâmetros. Esse pipe irá gerar uma string a partir de um array de strings, permitindo que o usuário defina os índices inicial e final para a seleção dos dados do array. Para isso, adicionaremos um novo arquivo chamado join.pipe.ts na pasta src/app com o seguinte conteúdo:
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
name: "join",
standalone: true,
})
export class JoinPipe implements PipeTransform {
transform(array: string[], start?: number, end?: number): any {
let result = array;
if (start !== undefined) {
if (end !== undefined) {
result = array.slice(start, end);
} else {
result = array.slice(start);
}
}
return result.join(", ");
}
}No método transform do JoinPipe, o primeiro parâmetro é o array, o segundo é o índice inicial opcional (start), e o terceiro é o índice final opcional (end). Usamos o método slice() para obter a parte desejada do array e o método join() para concatenar os elementos em uma string.
Aplicando o JoinPipe
Vamos agora usar o JoinPipe dentro de um componente:
import { Component } from "@angular/core";
import { JoinPipe } from "./join.pipe";
@Component({
selector: "my-app",
standalone: true,
imports: [JoinPipe],
template: `<div>{{ users | join }}</div>
<div>{{ users | join : 1 }}</div>
<div>{{ users | join : 1 : 3 }}</div>`,
})
export class AppComponent {
users = ["Tom", "Alice", "Sam", "Kate", "Bob"];
}Aqui, aplicamos o JoinPipe de diferentes maneiras: sem parâmetros, com um índice inicial, e com ambos os índices inicial e final.

Conclusão
Criar pipes personalizados em Angular oferece uma forma flexível de manipular e formatar dados na camada de exibição. Os pipes permitem uma separação clara entre lógica de formatação e a interface, promovendo um código mais limpo e reutilizável.