AngularJS: Controladores (Controllers)

Olá pessoal, beleza?

No post anterior, Introdução ao AngularJS, fizemos uma explanação sobre algumas características importantes do AngularJS. Hoje vamos falar sobre os controladores e as boas práticas que podem ser adotadas em sua utilização.

Entendendo os Controladores

Os Controladores (Controllers), como o próprio nome diz, são responsáveis pelo controle da aplicação. É neles que gerenciamos o fluxo de dados apresentados na view. Quando um controlador é anexado ao DOM, via ng-controller, um novo objeto do controlador será instanciado, de acordo com a especificação do construtor. Na sequência, um novo escopo ($scope) filho será criado e disponibilizado como um parâmetro injetável no construtor do controlador.

[Boa Prática]

  1. O controlador deve ser utilizado apenas para a lógica de negócio da aplicação. É nele que devemos setar o estado inicial do $scope e/ou adicionar comportamento.
  2. Não é recomendado usá-lo para:
    • Manipular o DOM: para a manipulação do DOM é aconselhável utilizar diretivas, com o intúito de encapsular esse comportamento. Ademais, com essa prática o código fica mais manutenível e testável.
    • Formatar Inputs: para isso use os controladores de formulários.
    • Filtrar Dados: o AngularJS dispõe de filtros padrão, além da opção de escrever filtros customizados.
    • Compartilhar código: para compartilhar estados ou dados com outros controladores devemos utilizar as factories/services.

Vamos pegar o exemplo do post Introdução ao AngularJS e adicionar o controlador, aqui você pode vê-lo rodando:

Neste exemplo, criamos o controlador (MeuController) no módulo apputilizando o método controller(). Esse método o mantém fora do escopo global. O objeto $scope é inserido dentro do MeuController através do mecanismo de injeção de dependência. Depois utilizamos a diretiva ng-controller, na div, para anexar o nosso controlador ao DOM.

Adicionando comportamento ao $scope

Quando queremos executar alguma ação na view, precisamos adicionar comportamento ao escopo. Antes disso, no entanto, é necessário anexar os métodos ao $scope. Assim, eles ficarão disponíveis para a camada de visão.

O código abaixo pode ser visto rodando aqui.

Para adicionar um item a lista de ítens, foi anexado ao $scope o método addItem ($scope.addItem). Já para utilizar o método addItem, utilizamos a diretiva ng-click. Sempre que houver o evento de click no botão o método será chamado.

Para exibir os itens adicionados utilizamos a diretiva ng-repeat. Quando um item for adicionado um novo elemento <li> será criado.

Nota: Para evitar o erro Error: ngRepeat:dupes na diretiva ng-repeat quando adicionamos ítens duplicados, é necessário usar o ‘track by’. O uso é indispensável porque o AngularJS utiliza uma chave única para ligar o nó do DOM ao elemento que está iterando. Mais detalhes sobre o assunto aqui.

Herança de $scope

Quando adicionamos os controllers em hierarquias, um dentro do outro, temos uma herança de escopos. Isso acontece porque a diretiva ng-controller cria um novo $scope filho, então o $scope que cada controlador recebe terá acesso aos métodos e atributos do controlador acima na hierarquia.

O código abaixo pode ser visto rodando aqui.

Como resultado desse aninhamento de controladores, são criados quatro objetos $scope (o root scope e um $scope para cada controlador). Para acessar uma propriedade do escopo pai, nós usamos o $parent.

Ainda há propriedades dos controladores que podem ser exploradas como, por exemplo, o uso do controller as ao invés do $scope. Vocês podem ver nesse plunker um exemplo utilizando o controller as e outras boas práticas, como o conceito de responsabilidade única (single responsability) para os arquivos javascript.

Por hoje é isso pessoal, espero que tenham gostado.

Abraços e até a próxima!