Quando falamos em formulários web, a entrada de dados deve sempre ser tratada. Todo e qualquer dado fornecido por um usuário deve ser sanitizado, tratado.
Desde números de telefone até datas e códigos de cartão de crédito, garantir a precisão e consistência dessas informações deve ser uma das prioridades do projeto. As máscaras em inputs surgem como uma solução elegante para ajudar nesse problema.
Em termos simples, uma máscara é como uma camada de orientação para o seu formulário. Ela define o formato esperado para a entrada de dados, guiando o usuário durante o preenchimento. Isso não apenas facilita a vida do usuário, mas também ajuda a prevenir erros comuns.
Utilizando o ngx-mask em um projeto Angular
Em projetos Angular, podemos recorrer a uma biblioteca chamada ngx-mask. Este pacote simplifica a aplicação de máscaras em inputs. Ele é particularmente útil quando se trata de formatar e validar dados de entrada, como números de telefone, datas, CPFs, entre outros, em formulários web.
Para demonstrar o uso da ngx-mask vou criar um projeto do zero utilizando as seguintes versões:
$ ng version
Angular CLI: 16.2.3
Node: 18.18.2
Package Manager: npm 9.8.1
OS: darwin arm64
No comando abaixo utilizei o --skip-git para não criar um repositório GIT local e usei o --minimal para não criar uma estrutura para testes unitários, já que o projeto será utilizado apenas para estudo:
$ ng new --skip-git --minimal utilizando-ngx-mask
? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? CSS
💡
Se quiser saber mais sobre as opções do ng new acesse este link ou digite ng new help no seu terminal.
Como o exemplo será construído utilizando Angular 16, a versão do ngx-mask deve ser a 16 conforme indicado na documentação oficial:
Com o projeto já criado e as dependências instaladas, para começar a utilizar o ngx-mask, importe o NgxMaskDirective e registre o provideNgxMask() no arquivo app.module.ts conforme a seguir:
Para conferir se a configuração está correta, alterei o AppComponent conforme a seguir:
Resultado:
O básico do ngx-mask
Uma vez configurado o ngx-mask, podemos utilizar o atributo mask nos inputs para configurar a máscara. Por exemplo:
O (, ) e espaço são special characters e o 0 e 9 são patterns. Isto significa que quando o usuário digitar algo, os special characters serão mantidos no input e o 0 e 9 substituídos pelos números que o usuário digitar, sendo que 9 é um número opcional.
Segundo a documentação, por padrão a lista de special characters é a seguinte:
- / ( ) . : space + , @ [ ] " '
Novamente, os special characters são valores fixos no seu input, são valores que o usuário não pode alterar, por exemplo, o preenchimento da máscara [0] (0)-0 pode ser [3] (4)-5.
Lista dos patterns:
0: somente número
9: somente número, porém, opcional
A: letra (maiúscula ou minúscula) ou número
S: somente letra (minúscula ou maiúscula)
U: somente letra maiúscula
L: somente letra minúscula
Além dessa lista de patterns, há outras opções como por exemplo:
IP - aplica uma máscara e valida o valor digitado
percent - utilizado para porcentagem
CPF_CNPJ - aplica uma máscara para CPF ou CNPJ
Hh:m0:s0 - máscara para hora (24h), minuto e segundo
Por padrão do ngx-mask, caso algum input não esteja preenchido com a máscara corretamente, o FormControl associado ao input é invalidado. Essa opção pode ser controlada através do atributo [validation]="true | false" (sendo o valor padrão true).
No exemplo a seguir, criei um formulário que utiliza a máscara em todos os inputs. Somente no primeiro input, CPF, deixei o [validation]="false" para demonstrar esse comportamento. Observe o código e o resultado a seguir:
💡
Observe que o trecho {{ form.value | json }} imprime o valor do formulário na tela.
Como resultado, observe que não preenchemos completamente os campos CPF nem Telefone; no entanto, apenas o campo Telefone ficou inválido. Isso ocorre porque configuramos no ngx-mask para que o FormControl vinculado ao CPF não seja considerado inválido caso a máscara não tenha sido totalmente preenchida.
Obtendo o valor com a máscara
Quando aplicamos a máscara 000.000.000-00 a um input e o vinculamos a um FormControl, após o usuário digitar o valor no input, ele visualizará na tela algo como 123.123.123-12. Entretanto, o valor obtido no FormControl.value será 12312312312, ou seja, por padrão, os caracteres especiais (special characters) não são incluídos no FormControl.value.
Em alguns cenários, como por exemplo, IP e Data, é interessante ter o valor completo, ou seja, com os pontos e barras. A boa notícia é que a ngx-mask já oferece essa opção através do atributo [dropSpecialCharacters]="true | false" (default: true).
Para demonstrar, utilizei o código HTML mencionado um pouco mais acima e adicionei o [dropSpecialCharacters]="false" no campo IP."
Veja na parte inferior da imagem que o valor do cpf contém apenas números e o valor do ip tem os números e os pontos.
Formulário com validação do CPF, telefone, IP e data com máscaras
Por fim, adicionei algumas validações no formulário, sendo algumas nativas e outras customizadas (ver arquivo app.validators.ts abaixo). Além disso, fiz pequenas modificações no HTML para exibir de forma amigável algumas mensagens de erro. Veja a seguir o código fonte:
Um último ponto que vale comentar é que, por padrão, as validações são aplicadas no evento onBlur, ou seja, quando o usuário clica no input e depois sai. Se quiser modificar este comportamento e validar conforme o usuário digita, utilize a opção updateOn na configuração do FormControl.
Considerações
Ao incorporar máscaras nos inputs, proporcionamos não apenas uma diretriz visual para os usuários, mas também estabelecemos um mecanismo que promove a consistência dos dados. Essa abordagem não só simplifica o processo de preenchimento, mas também desempenha um papel crucial na prevenção de erros comuns.
Além disso, a ngx-mask, integrada ao Angular, destaca-se por sua flexibilidade e facilidade de implementação. Seja lidando com formatos específicos de data, exigências precisas para números de telefone ou padrões específicos para códigos, a biblioteca oferece uma gama de opções configuráveis.