Como construir um pipe para formatar CPF - Angular 2+
Processar informações para exibi-lás em um determinado formato, com certeza é uma das tarefas mais comuns para desenvolvedores. Raramente veremos um número de telefone sendo exibido na tela como 55119888888888
mas sim como +55 11 9 88888-8888
. Falando de moeda, não vamos exibir na tela um valor bruto como 1.45
mas sim R$ 1,45
.
Este processamento com foco na formatação/transformação da informação, pode ser feito através da utilização dos Pipes no contexto do Angular. Para deixar as coisas mais claras, vamos utilizar como exemplo um pipe nativo do Angular para deixar um texto com letras maiúsculas:
<div>{{'meu texto' | uppercase}}</div>
O resultado será: <div>MEU TEXTO</div>
Nativamente temos os seguintes pipes prontos para uso:
Link da documentação oficial dos pipes acima: https://angular.io/guide/pipes
Como construir um pipe customizado
Para a construção do nosso estudo, vamos supor que os valores dos CPFs chegarão ao frontend em formato numérico ou texto, por exemplo:
[
'11122233344',
11122233344,
1122233344
]
Nosso objetivo é formatar estes valores de modo a sempre exibir o seguinte: 999.999.999-99
. Caso o número do CPF seja menor que 11, complementaremos com zeros á esquerda.
Construção do pipe
Para construir um pipe é necessário criar uma classe e implementar o PipeTransform
conforme o exemplo abaixo:
// cpf.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'cpf' })
export class CpfPipe implements PipeTransform {
transform(value: string|number): string {
return value + 'teste';
}
}
Olhando o código acima, o método transform
receberá um valor e retornará uma string
com a palavra 'teste'
concatenada no final. Mais a frente iremos desenvolver a lógica de formatação do CPF.
Após criar o arquivo cpf.pipe.ts
temos que declará-lo em algum módulo. No nosso cenário de testes vamos registrar este novo pipe no AppModule
, arquivo app.module.ts
, que já tem registrado o componente que iremos utilizar para efetuar os testes, app.component.ts
:
// app.module.ts
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CpfPipe } from './cpf.pipe';
@NgModule({
declarations: [
AppComponent, // <<< Componente que irá utilizar o pipe
CpfPipe, // <<< Declaração do pipe
],
imports: [
AppRoutingModule,
BrowserModule,
CommonModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
itens = [
'11122233344',
11122233344,
1122233344
];
}
<!-- app.component.html -->
<html>
<head>
<title>Testes</title>
</head>
<body>
<ul>
<li *ngFor="let item of itens">
{{item | cpf}}
</li>
</ul>
<router-outlet></router-outlet>
</body>
</html>
Após executar a aplicação (ng serve
) podemos ver o resultado na tela do navegador:
Então até este ponto nosso pipe está funcionando. Agora vamos começar a desenvolver a lógica para formatar o CPF.
Construindo um pipe para formatar CPF
A lógica de formatação ficará dentro do arquivo cpf.pipe.ts
. Vamos construir a lógica da seguinte forma:
- Caso o tamanho do
valor
seja menor que 11, completaremos com zeros à esquerda. - Caso o tamanho da
string
seja maior que 11, vamos pegar apenas até a décima primeira posição. - Vamos retirar do
valor
qualquer coisa que não seja um número. Então se chegar algo como111-22233344
o resultado será11122233344
- Vamor extraír 3 grupos de 3 dígitos e depois 1 grupo de 2 dígitos para formatar o CPF conforme o seguinte:
(3 dígitos).(3 dígitos).(3 dígitos)-(2 dígitos)
:
// cpf.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'cpf' })
export class CpfPipe implements PipeTransform {
transform(value: string|number): string {
let valorFormatado = value + '';
valorFormatado = valorFormatado
.padStart(11, '0') // item 1
.substr(0, 11) // item 2
.replace(/[^0-9]/, '') // item 3
.replace( // item 4
/(\d{3})(\d{3})(\d{3})(\d{2})/,
'$1.$2.$3-$4'
);
return valorFormatado;
}
}
Ao salvar o arquivo acima, nossa página será recarregada com o seguinte resultado:
Agora que a formatação do CPF já está OK, vamos avançar nos estudos e ver como podemos passar parâmetros para o nosso pipe para por exemplo, escolhar mascarar (ocultar) ou não o número do CPF.
Adicionando uma opção para máscarar alguns números do CPF
Repare que o método transform
do arquivo cpf.pipe.ts
recebe apenas um valor. Para receber um segundo valor podemos adicionar um novo parâmetro, ocultarAlgunsValores
, e passar o valor para o método separando os argumentos por :
no template conforme o código abaixo:
// cpf.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'cpf' })
export class CpfPipe implements PipeTransform {
transform(value: string|number,
ocultarAlgunsValores: boolean = false): string {
let valorFormatado = value + '';
valorFormatado = valorFormatado
.padStart(11, '0')
.substr(0, 11)
.replace(/[^0-9]/, '')
.replace(
/(\d{3})(\d{3})(\d{3})(\d{2})/,
'$1.$2.$3-$4'
);
if (ocultarAlgunsValores) {
valorFormatado =
'XXX.' + valorFormatado.substr(4, 7) + '-XX';
}
return valorFormatado;
}
}
<!-- app.component.html -->
<!-- ... (código ocultado) ... -->
<li *ngFor="let item of itens">
{{item | cpf : true}}
</li>
<!-- ... (código ocultado) ... -->
Resultado da renderização:
Considerações
O pipe é um recurso extremamente útil para formatar ou transformar informações no seu template. É um recurso simples de ser implementado e muito útil, inclusive para questões de performance que serão abordadas em uma outra hora.
Links interessantes: