Porque utilizar AngularJS no seu próximo projeto

Vamos começar pela definição: AngularJS é um framework JavaScript para construção de aplicações web dinâmicas, comumente referenciado como um framework MVC client side. Essa definição não está errada, mas o fato é que MVC é um padrão para dividir uma aplicação em diferentes partes (modelo, visão e controle), cada uma com suas respectivas responsabilidades. O AngularJS  não implementa um MVC na sua forma tradicional, mas algo próximo de um MVVM (Model – View – ViewModel). Logo, seu próprio time de desenvolvimento resolveu batizá-lo, carinhosamente, de um framework MVW  – Model View Whatever. Bem, o time de desenvolvimento do Angular dispensa apresentação, ele nasceu e é mantido por uma empresa que entende de web, o Google.

“AngularJS – Superheroic JavaScript MVW Framework”

A principal característica do AngularJS é que ele funciona como uma extensão do HTML, diferente de outros frameworks JavaScript, não é necessário manipular o DOM. Isso possibilita a criação de um front end mais organizado e sem a necessidade de manipular “html + dados”.

Suas principais características são:

  • Two-way Data binding
  • Injeção de Dependências
  • Criação de diretivas (Extensão do HTML)
  • Modularização e reuso (Controllers, Services e Filters)
  • Testabilidade

Basicão


<html ng-app>
 <head>
     <title>AngularJS</title>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
 </head>
 <body>
     <p>Meu nome é: {{ nome }}</p>
     <input type="text" ng-model="nome">
 </body>
</html> 

Este é o exemplo mais básico em AngularJS. A diretiva ng-app na tag <html> inicializa a aplicação e define esta tag como o elemento root da aplicação, tudo a partir dela pode ser gerenciado pelo Angular. Ao digitar algo no input o nome será atualizado em realtime na tela. Essa mágica é chamada de Two-way data binding. Qualquer interação na view será refletida no modelo e vice-versa, isso é feito através do objeto $scope, criado automaticamente pelo angular. A propriedade ng-model é responsável por fazer o canal de comunicação e a sintaxe utilizada é o “bigode-bigode”: {{ atributo }}. Note que até aqui não escrevemos nenhum código JavaScript.

Controllers

Para entender como é feito o vínculo da view com o modelo, e como o angular permite organizamos nossa aplicação com a chamada de Controllers, segue o código a seguir:

cervejas.html


<div ng-controller="CervejaController">
 <form name="form">
     <input type="text" placeholder="Cerveja" ng-model="cerveja.nome">
     <input type="text" placeholder="Cervejaria" ng-model="cerveja.cervejaria">
     <button ng-click="adicionar()">Adicionar</button>
 </form>
 <table>
 <thead>
     <tr>
         <th>Cerveja</th>
         <th>Cervejaria</th>
     </tr>
 </thead>
 <tbody>
     <tr ng-repeat="cerveja in cervejas">
         <td>{{ cerveja.nome }}</td>
         <td>{{ cerveja.cervejaria }}</td>
     </tr>
 </tbody>
 </table>
</div> 

CervejaController.js


function CervejaController($scope) {
 $scope.cervejas = [ { nome : 'Cerpinha', cervejaria : 'Cerpa'},
                     { nome : 'Tijuca', cervejaria : 'Cerpa' } ];

 $scope.adicionar = function() {
     $scope.cervejas.push({nome : $scope.cerveja.nome,
                           cervejaria : $scope.cerveja.cervejaria});
     $scope.limpar();
 };

 $scope.limpar = function() {
     $scope.cerveja = {nome: '', cervejaria: ''};
 };
}

A diretiva ng-controller vincula um elemento html com um Controller JavaScript, no caso CervejaController. Tudo a partir desta div pode ser controlado por este Controller. O button chama através da diretiva ng-click a função adicionar(), definida dentro do nosso Controller. Esta função adiciona uma nova cerveja na listagem e limpa os campos do formulário. Ao iniciar o controller, por padrão é adicionada duas cervejas na listagem, também poderíamos usar a diretiva ng-init neste caso. Note que a variável $scope foi recebida como argumento do Controller. Este é um exemplo de injeção de dependência feito automaticamente pelo AngularJS, um dos principais recursos do framework.

Outra diretiva interessante presente neste exemplo é a ng-repeat, que permite iterar em listas de forma bem simples e intuitiva, no formato <elemento> in <coleção>.

Filters

Outro recurso muito interessante e nativo do framework é a aplicação de filters. Os filtros servem para transformar o resultado de uma expressão, aplicando algum tipo de formatação ou restrição nos dados. Segue o exemplo:


<h2>Busca</h2>
Cerveja: <input ng-model="search.nome">
Cervejaria: <input ng-model="search.cervejaria">
<table>
 <thead>
    <tr>
        <th><a href="">Cerveja</a></th>
        <th>Cervejaria</th>
    </tr>
  </thead>
 <tbody>
    <tr ng-repeat="cerveja in cervejas | filter:search | orderBy:'nome'">
        <td>{{ cerveja.nome | uppercase }}</td>
        <td>{{ cerveja.cervejaria }}</td>
    </tr>
 </tbody>
</table> 

A sintaxe dos filtros funciona com a inclusão de um pipeline “|” dentro da expressão. No exemplo foi adicionado dois inputs, para filtrar por nome e por cervejaria, através do objeto search, incorporado na diretiva ng-repeat: “filter:search”. Os filtros também suportam ordenação através da propriedade orderBy. Adicionalmente existem alguns filtros padrão no Angular, como uppercase, lowercase e date. Há também a possibilidade de criar filtros customizados da seguinte forma:


App.filter('meuFiltro', function() {
    return function(data) {
        return data;
    };
});

Services

O conceito de separação de responsabilidades está presente no AngularJS através da aplicação de Services. Basicamente, os serviços são funções javascript que devem executar funções específicas, bem definidas, de fácil manutenção e testáveis. Dessa forma é possível modularizar e reaproveitar serviços em diferentes controladores, por meio da injeção de dependências, da seguinte forma:


//app.js
var app = angular.module("app", []);

app.service('CervejaService', function(){
    this.remover = function(cervejas, cerveja) {
        var index = cervejas.indexOf(cerveja);
        cervejas.splice(index, 1);
    };
});

//CervejaController.js
function CervejaController($scope, CervejaService) {
    //...
    $scope.remover = function(cerveja) {
        CervejaService.remover($scope.cervejas, cerveja);
    };
}


//cervejas.html
<table>
    <thead>
        <tr>
            <th><a href="">Cerveja</a></th>
            <th>Cervejaria</th>
            <th></th>
        </tr>
     </thead>
     <tbody>
        <tr ng-repeat="cerveja in cervejas | filter:search | orderBy:'nome'">
             <td>{{ cerveja.nome | uppercase }}</td>
             <td>{{ cerveja.cervejaria }}</td>
             <td><button ng-click="remover(cerveja)">Remover</button></td>
        </tr>
     </tbody>
</table> 

Na primeira linha, é iniciado o módulo principal da aplicação, o primeiro argumento é o nome do módulo, o segundo é um lista de dependências externas que podem ser injetadas na aplicação, como plug-ins de controle de rotas, componentes de view, etc. Em seguida é definido o serviço CervejaService, nele implementamos uma função para remover uma cerveja de uma listagem, essa função pode ser usada em qualquer controller que injete este serviço. Para chamar a função de remoção, basta uma chamada via ng-click para a função remover(),definida no controller, para que o serviço seja invocado.

Jasmine

Graças a organização do código que o AngularJS nos proporciona, testá-lo se torna uma tarefa fácil. Para isso vamos usar o framework de teste Jasmine. Aliás, o próprio código do Angular é testado utilizando Jasmine. Precisamos importar apenas jasmine.js e o módulo de mocks do angular.


beforeEach(module('app'));
describe('CervejaController', function () {

    it('deve definir uma cerveja padrao com nome e cervejaria vazias', inject(function ($controller) {
        var scope = {};
        var ctrl = $controller('CervejaController', { $scope: scope });

        expect(scope.cerveja.nome).toBe('');
        expect(scope.cerveja.cervejaria).toBe('');
    }));

    it('deve iniciar com duas cervejas carregadas', inject(function ($controller) {
        var scope = {};
        var ctrl = $controller('CervejaController', { $scope: scope });

        expect(scope.cervejas.length).toBe(2);
    }));

    it('deve limpar uma cerveja', inject(function ($controller) {
        var scope = {};
        var ctrl = $controller('CervejaController', { $scope: scope });

        scope.cerveja = {nome: 'Cerpinha', cervejaria: 'Cerpa'};
        scope.limpar(); 

        expect(scope.cerveja.nome).toBe('');
        expect(scope.cerveja.cervejaria).toBe('');
    }));
});

A função beforeEach carrega o módulo antes de iniciarmos o teste do CervejaController. Basicamente foram definidos três testes, os dois primeiros testam o estado inicial do controller, o terceiro testa a função limpar. A função expect é responsável por fazer a asserção de nossos testes.

Daria para escrever um artigo só para os detalhes da implementação de testes com Jasmine e suas diferentes abordagens de cobertura dentro de aplicações com AngularJS.

Conclusões

As possibilidades do AngularJS não se esgotam aqui, existem vários recursos que não foram abordados. Mas o que foi apresentado serve de base pra você considerar utilizar este poderoso framework no seu próximo projeto.

Todo código apresentado aqui está disponível no github.

Anúncios

4 comentários sobre “Porque utilizar AngularJS no seu próximo projeto

  1. Post legal, Kaio. Parabéns. Angular é uma boa ferramenta. Mas aí ficou uma pergunta. Quando vc apresenta motivos para utilizar Angular em um próximo projeto, você consegue apontar projetos onde os fatores time/cultura/requisitos/negócio são mais ou menos favoráveis ao uso do Angular?

    Deixo esse link aqui (http://www.fse.guru/2-years-with-angular) para alimentar um pouco a discussão. Eu mesmo já usei Angular em algumas coisas e penso que ele se encaixa bem “nas mãos certas”.

    Abraços!

    Curtir

  2. Valeu Alexandre.

    Sobre a questão que levantaste, acho que a utilização do Angular se encaixa bem em times onde os papéis de desenvolvedores de front e backend são claros. A separação que o angular proporciona, até mesmo para mockar o serviços de backend, facilita um pouco o processo de desenvolvimento. Outro ponto é o que o Marcelio comentou, como tudo acaba sendo orientado a uma API Rest, fica fácil reutilizar. Contudo, nem todo mundo gosta e é adepto de JavaScript e seus callback hell, hehe, logo um time que não tenha afinidade com javascript, eu não recomendaria.

    Interessante o artigo que postaste sobre a utilização do angular. Nunca cheguei a analisar algum benchmark que analise a performance do angular em aplicações críticas. Apenas aqueles que o comparam a outros frameworks com a mesma ideologia, como backbone, ember, knockout, etc… Mas concordo quanto a utilização de style guides e padrões pra se conseguir manter uma organização mínima pensando na manutenção. Enfim, todas as tecnologias têm suas limitações e cenários onde não são adequadas.

    Curtir

  3. Pingback: Os 5 posts mais lidos do ano no blog do Tá Safo | Blog do Tá safo!

O que tu achas?

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s