Conteúdos
  1. 1. Abolir a função link
  2. 2. Diretivas de fábrica
    1. 2.1. Clipboard Events
    2. 2.2. Keyboard Events
    3. 2.3. Focus Events
    4. 2.4. Form Events
    5. 2.5. Mouse Events
    6. 2.6. Touch Events
  3. 3. Eventos customizados
  4. 4. Conclusão sobre eventos

O Angular, como diz a própria documentação, é um framework para criação de aplicações dinâmicas que aposta em código declarativo, dado que código assim é melhor para a programação de interfaces web.

O problema é que ainda assim as pessoas costumam esquecer a importância de usar código declarativo e o código da sua aplicação acaba perdendo um pouco da sua expressividade. Quer um exemplo? O excessivo uso da função link quando cria-se uma diretiva!

Neste post da série Angular por um desenvolvedor React vou discutir um pouco sobre como acho que devam ser usados os eventos dentro do Angular dado meu background com desenvolvimento com o React.

Uma das bases da expressividade de um código escrito usando Angular reside no fato de que você pode programar diretamente no HTML, através de tags e diretivas. Algo que chega até a ser curioso: quando o código coloca HTML no JavaScript, como faz o React, dizem ser loucura e mistura de conceitos; quando coloca-se JavaScript no HTML, como faz o Angular, chamam de “maior expressividade do template”, vai entender.

Existem diversas diretivas que permitem que você trabalhe com eventos dentro do seu template. Atente-se ao fato que “evento” neste post diz respeito à eventos do DOM, como click, submit, entre outros. Estas diretivas cortam a necessidade de cerca de 95% dos casos onde as pessoas costumam usar a função link (fonte desta estatística: minha imaginação fértil). Então, assim como paramos de usar o $scope no primeiro post da série, neste post vamos parar de usar mais uma outra coisa:

Talvez pareça radical demais, loucura demais. Mas vamos começar com a premissa de nunca usar a função link. Eu sei que você vai arrumar um jeito de encontrar casos em que é extremamente necessário. Para estes casos também temos um jeito, mas deixemos eles de lado por enquanto e vamos para os casos mais comuns.

Caso você não saiba, a função link de uma diretiva especifica uma função que te dá acesso ao elemento do DOM em que a diretiva está montada, comumente usado para adicionar event listeners aos elementos. Notou aí o problema com a expressividade? Se você coloca os seus listeners somente dentro da função link seu código perde uma parte da expressividade. Ao olhar o template da sua diretiva, um usuário não saberá os eventos que acontecem por ali.

Portanto vamos lá: abolindo a função link!

Diretivas de fábrica

O Angular já vem de fábrica com várias diretivas para adicionar event listeners ao seus elementos. Eles funcionam bem semelhante aos eventos suportados pelo React. Seguindo a documentação do sistema de eventos do React, eu separei aqui uma lista, na mesma ordem, dos eventos providos de fábrica pelo Angular através de diretivas:

Clipboard Events

Keyboard Events

Focus Events

Form Events

Mouse Events

Touch Events

Depende de ngTouch.

Notou a quantidade de diretivas para eventos do DOM que você já tem por padrão? Veja abaixo um exemplo de um código usando a função link:

1
2
3
4
5
6
7
8
9
// ElementDirective.js
// ...
link: function(scope, element, attrs, controller) {
element
.find('.my-button')
.on('click', function(e) {
controller.handleClick(e);
});
}
1
2
3
4
// element.html
<div>
<button class="my-button">Click me</button>
</div>

E agora um código usando somente diretivas:

1
2
3
<div>
<button ng-click="ctrl.handleClick($event)">Click me</button>
</div>

Notou como o segundo é mais claro para quem lê o código do template? E mais! Possuir código que delega um evento do DOM para um método do controller da sua diretiva diminui a quantidade de código não testado (já que a função link raramente é testada), aumentando seu code coverage se o método no seu controller for coberto por testes.

Caso você esteja acompanhando a série de posts também pelo repositório no Github, veja aqui um exemplo de código declarativo com evento.

Eventos customizados

Ok, ok, sabemos que as vezes você precisará de eventos customizados de algum tipo no seu template. Como lidar com isso?

Primeiramente vamos concordar que esses casos são exceções, então vamos criar uma exceção para algo que já falamos neste post: abolir o uso do link.

Você deve se lembrar do primeiro post da série sobre Angular por um desenvolvedor React quando falamos sobre diretivas helpers, certo? Estas diretivas eram as únicas que possuiam escopo não-isolado.

Se você entendeu que tipo de diretivas essas são, deve ter também relacionado que diretivas como ng-click, ng-submit e afins se encaixam neste tipo de diretiva.

Então vamos às nossas novas regras neste post:

  • O uso da função link de uma diretiva deve acontecer somente em diretivas helper;
  • Nenhum tipo de lógica deve estar contida dentro do event listener, somente delegação de chamada para o controller do componente;
  • E, por último: sempre que precisar de um evento custom crie uma diretiva helper o mais genérica possível para este evento e teste-a.

Conclusão sobre eventos

Este post é bem curto mas a ideia dele é ir direto ao ponto: tenha o código para eventos também declarativo.

Permitir que a pessoa que lê seu código entenda-o mesmo quando vê somente o template significa que seu código está bem mais legível e expressivo, e aproveita uma feature bastante importante do Angular.

Qualquer sugestão, crítica ou algo do gênero, é só comentar ali em baixo!

Conteúdos
  1. 1. Abolir a função link
  2. 2. Diretivas de fábrica
    1. 2.1. Clipboard Events
    2. 2.2. Keyboard Events
    3. 2.3. Focus Events
    4. 2.4. Form Events
    5. 2.5. Mouse Events
    6. 2.6. Touch Events
  3. 3. Eventos customizados
  4. 4. Conclusão sobre eventos