Desmistificando as poderosas diretivas no Angular

Andrew Rosário
4 min readJun 14, 2021

--

Durante o nosso aprendizado com o Angular, focamos na maior parte do tempo no desenvolvimento de componentes. Mas o framework também disponibiliza outros recursos muito úteis, como as diretivas.

As diretivas são classes que adicionam comportamentos nos elementos do template. *ngIf e *ngFor são amplamente utilizadas, porém podemos criar nossas próprias diretivas. Eu vejo que muitas pessoas não possuem o hábito de utilizá-las ao seu favor, seja por falta de conhecimento ou comodismo.

Elas são nossas aliadas para escrever códigos com maior qualidade e reuso. Trazendo os princípios do SOLID para dentro do Angular, as diretivas nos ajudam a aplicar as letras “S” e “O”.

Single Responsability Principle: Muitas vezes precisamos adicionar comportamentos extras em nossos componentes, ao invés de atribuir mais uma responsabilidade a eles, transferimos para uma diretiva que pode ser reutilizável.

Open Closed Principle: Deixamos nossos componentes fechados para modificações e abertos para extensões, neste caso as extensões podem ser as diretivas.

Exemplos Práticos

Abaixo veremos alguns casos de uso onde criamos diretivas para aplicar estes conceitos.

Exemplo 1 — @HostListener

Vamos analisar o seguinte componente:

Temos um elemento pai com uma ação de click e um elemento filho em forma de botão que também tem uma ação de click. Se clicarmos no botão, tanto a função clickButton quanto a função clickDiv será chamada. Isso ocorre por causa do Event Bubbling. O evento de click irá se propagar como “bolhas” por todos os elementos que estão aninhados a ele. Para chamarmos somente a função do clickButton utilizamos o stopPropagation.

Problema resolvido, porém “sujamos” o nosso código com um comportamento que não deveria ser específico desse componente. Solução: vamos criar uma diretiva para desacoplar esta lógica.

Com o decorator @HostListener, podemos ouvir eventos do DOM e manipularmos de acordo com a nossa necessidade. Neste exemplo queremos ouvir o evento de click e parar a propagação do mesmo.

Agora é só utilizar nossa diretiva no componente e em qualquer outro lugar onde ela seja necessária.

Exemplo 2 — @HostBinding

Em muitos casos precisamos customizar alguns estilos de componentes baseados em condições. Para evitar a inserção dessas regras no componente, podemos criar uma diretiva para realizar a tarefa. Veremos um exemplo onde precisamos aplicar um background-color padrão azul mas podemos alterá-lo também.

Aqui utilizamos o decorator @HostBinding. Com ele podemos fazer uma associação com algum atributo do HTML como um estilo ou uma classe CSS por exemplo. No caso associamos o background-color.

Perceba que temos um @Input com o mesmo nome da diretiva, desta forma fica ainda mais fácil para atribuir uma cor personalizada. Observe o uso dela, no primeiro elemento aplicamos o fundo azul como padrão e no segundo elemento aplicamos a cor amarela.

Exemplo 3 — Injeção de Dependência com NgControl

Temos um cenário onde precisamos manipular controles de um formulário. Se o controle estiver válido, preenchemos com uma borda verde, se estiver inválido preenchemos com uma borda vermelha.

Com certeza esse é um caso para criar uma diretiva e tornar esta lógica reutilizável. Mas como podemos manipular o controle? A resposta está na injeção de dependência. Injetamos a classe NgControl que irá associar ao nosso controle, seja ele um FormControl, FormControlName ou NgModel.

Agora com a instância do controle, temos acesso a todos os atributos do mesmo, inclusive o status. Então basta realizar uma lógica, aproveitando mais uma vez o @HostBinding.

Aplicamos ela no componente e independente de quais sejam os validadores teremos acesso a eles na diretiva.

Exemplo 4 — Injeção de Dependência com Componente

Esta é mais uma situação envolvendo formulários. Temos um componente que implementa um Form com certas validações e em algum lugar precisamos desse mesmo formulário só que com alguma validação a mais. A primeira ideia é fazer uma condicional no componente para aplicar essas validações e utilizá-lo nos dois lugares. Só que fazendo isso estamos quebrando mais uma vez o Open Closed Principle. A ideia aqui é criar uma diretiva ligada ao componente para aplicar a validação.

Vamos utilizar o próprio componente do exemplo anterior para isso. No caso ele possui um validador Required. Agora queremos inserir também um minLength de 5 caracteres. Na nossa diretiva injetaremos então o próprio componente. Agora temos acesso a todas as propriedades públicas dele. Iremos capturar o controle e atribuir os validadores com a função setValidators.

Um detalhe importante a ser mencionado aqui é o seletor da diretiva. Para evitarmos que ela seja utilizada em outros componentes ou elementos, informamos explicitamente o seletor do componente que está ligado a ela.

Agora podemos utilizar o componente com este comportamento de uma forma muito mais elegante.

Conclusão

Espero que este artigo tenha mostrado como as diretivas são úteis em diversos cenários e faça com que você incorpore-as cada vez mais no dia-a-dia nas suas aplicações. Abaixo você pode conferir estes exemplos no StackBlitz.

Estes foram apenas alguns exemplos de utilização, mas existem muitas outras técnicas incríveis que dão muito valor ao nosso código. Utiliza uma diretiva com técnicas diferentes das que estão descritas neste artigo? Compartilha com a gente nos comentários!

--

--

Andrew Rosário
Andrew Rosário

Written by Andrew Rosário

Desenvolvedor Front-end, mentor e palestrante. Apaixonado por tecnologia e por compartilhar conhecimento.

Responses (2)