Guia definitivo para aprender AngularJs em um dia

23
Guia Definitivo para Aprender AngularJS em Um Dia Fonte: http://javascriptbrasil.com/2013/10/18/guia-definitivo-para-aprender-angularjs-em-um-dia/ O que é AngularJS? Angular é um framework client-side MVC/MVVM feito em JavaScript, essencial para modernas „single page web applications – SPA‟ (aplicações de uma página) e até mesmo sites. É um grande salto para o futuro do HTML e para o que o HTML5 traz, e é um sopro de ar fresco quando se está lidando com a web moderna. Este post é um curso completo „do início ao fim‟, feito a partir de minhas experiências, conselhos e melhores práticas, aprendidas usando-o. Terminologia Angular tem uma curva de aprendizagem de curto prazo, mas devemos nos familiarizar com a terminologia e “pensamento MVC”. MVC significa Model-View-Controller (Modelo-Visão-Controlador). MVC Você provavelmente ouviu sobre MVC, usado em várias linguagens de programação com o sentido de estruturação/arquiteturação de aplicações/softwares. Aqui está o significado de cada uma das partes: Model (Modelo): é a estrutura de dado atrás de uma parte específica da aplicação, usualmente portada em JSON. Leia sobre JSON antes de iniciar com Angular, pois é essencial para a comunicação do seu servidor e „view‟. Por exemplo, um grupo de „IDs de usuário‟ pode seguir o seguinte modelo: 1 2 3 4 5 6 7 8 9 { "users": [{ "name": "Joe Bloggs", "id": "82047392" }, { "name": "John Doe", "id": "65198013" }] } Você vai então pegar esta informação ou do servidor via XHR (XMLHttpRequest), com jQuery você conhece isto como o método

Transcript of Guia definitivo para aprender AngularJs em um dia

Page 1: Guia definitivo para aprender AngularJs em um dia

Guia Definitivo para Aprender AngularJS em Um Dia Fonte: http://javascriptbrasil.com/2013/10/18/guia-definitivo-para-aprender-angularjs-em-um-dia/

O que é AngularJS?

Angular é um framework client-side MVC/MVVM feito em JavaScript,

essencial para modernas „single page web applications – SPA‟

(aplicações de uma página) e até mesmo sites. É um grande salto

para o futuro do HTML e para o que o HTML5 traz, e é um sopro de ar

fresco quando se está lidando com a web moderna. Este post é um

curso completo „do início ao fim‟, feito a partir de minhas experiências,

conselhos e melhores práticas, aprendidas usando-o.

Terminologia

Angular tem uma curva de aprendizagem de curto prazo, mas

devemos nos familiarizar com a terminologia e “pensamento MVC”.

MVC significa Model-View-Controller (Modelo-Visão-Controlador).

MVC

Você provavelmente ouviu sobre MVC, usado em várias linguagens de

programação com o sentido de estruturação/arquiteturação de

aplicações/softwares. Aqui está o significado de cada uma das partes:

Model (Modelo): é a estrutura de dado atrás de uma parte específica

da aplicação, usualmente portada em JSON. Leia sobre JSON antes

de iniciar com Angular, pois é essencial para a comunicação do seu

servidor e „view‟. Por exemplo, um grupo de „IDs de usuário‟ pode

seguir o seguinte modelo:

1

2

3

4

5

6

7

8

9

{

"users": [{

"name": "Joe Bloggs",

"id": "82047392"

}, {

"name": "John Doe",

"id": "65198013"

}]

}

Você vai então pegar esta informação ou do servidor via XHR

(XMLHttpRequest), com jQuery você conhece isto como o método

Page 2: Guia definitivo para aprender AngularJs em um dia

$.ajax e com os envólucros (wraps) do Angular como $http, ou isto vai

ser escrito no seu código enquanto a página é parseada (de um banco

de dados). Você pode então enviar atualizações para seu modelo e

pegá-las de volta.

View (Visão): O „view‟ é simples, ele é seu HTML e/ou saída

renderizada. Usando um framework MVC, você irá pegar os dados do

„Model‟ que atualiza seu „View‟ e mostrar as informações relevantes

em seu HTML.

Controller (Controlador): Ele faz o que diz na embalagem, controla

coisas. Mas que coisas? Dados. „Controllers‟ são seu acesso direto do

servidor para o „view‟, seu intermediário, atualizando os dados em

tempo real via comunicadores entre o servidor e o cliente.

Criação de Um Projeto AngularJS (mínimo essencial)

Primeiro, nós precisamos de fato configurar o essencial para um

projeto Angular. Há certas coisas para se observar antes de

começarmos, que geralmente consiste em uma declaração ng-

app para definir sua aplicação, um Controller para conversar com sua

„View‟, e alguma ligação DOM e inclusão do Angular. Aqui temos o

mínimo essencial:

Um pouco de HTML com declarações ng-*:

1

2

3

4

5

<div ng-app="myApp">

<div ng-controller="MainCtrl">

<!-- controlador lógico -->

</div>

</div>

Um módulo Angular e um Controlador:

1

2

3

4

5

var myApp = angular.module('myApp', []);

myApp.controller('MainCtrl', ['$scope', function ($scope) {

// Controller mágico

}]);

Antes de aprofundarmos, nós precisamos criar um módulo Angular o

qual toda nossa lógica será acoplada. Há várias formas de declarar

módulos, e você pode encadear toda sua lógica assim (Eu não gosto

deste método):

1 angular.module('myApp', [])

Page 3: Guia definitivo para aprender AngularJs em um dia

2

3

4

.controller('MainCtrl', ['$scope', function ($scope) {...}])

.controller('NavCtrl', ['$scope', function ($scope) {...}])

.controller('UserCtrl', ['$scope', function ($scope) {...}]);

Criar um módulo global provou ser a melhor maneira em projetos

Angular que eu trabalhei. A falta de ponto e vírgula e o fechamento

acidental do encadeamento é notoriamente contraproducente

(improdutivo) e frequentemente nos leva a erros de compilação

desnecessários. Faça assim:

1

2

3

4

var myApp = angular.module('myApp', []);

myApp.controller('MainCtrl', ['$scope', function ($scope) {...}]);

myApp.controller('NavCtrl', ['$scope', function ($scope) {...}]);

myApp.controller('UserCtrl', ['$scope', function ($scope) {...}]);

Cada novo arquivo que eu criar simplemente pego o namespace e

automaticamente estamos conectados com a aplicação. Sim, eu estou

criando novos arquivos para cada Controlador, Diretiva, Factory e tudo

mais (você vai me agradecer por isto). Concatene-os e envie o script

único no DOM dinamicamente usando algo como Grunt.

Controladores

Agora que você compreendeu o conceito do MVC e a configuração

básica, vamos verificar a implementação do Angular e como você

pode trabalhar com Controladores.

Pegando o exemplo acima, nós podemos fazer um „baby-step‟ (passo

de bebê) em como inserir alguns dados no DOM a partir de um

controlador. O Angular usa estilo de template com sintaxe {{

handlebars }} para conversar com o seu HTML. O HTML

(preferencialmente) não deve conter textos físicos ou pesados

códigos, para que se faça o melhor do Angular. Aqui temos um

exemplo de inserção de uma simples String no DOM.

1

2

3

4

5

<div ng-app="myApp">

<div ng-controller="MainCtrl">

{{ text }}

</div>

</div>

1

2

3

4

5

var myApp = angular.module('myApp', []);

myApp.controller('MainCtrl', ['$scope', function ($scope) {

$scope.text = 'Olá, fã de Angular =)';

}]);

Page 4: Guia definitivo para aprender AngularJs em um dia

E o resultado ao vivo: http://jsfiddle.net/toddmotto/mN7QB/light/

O regra chave aqui é o conceito de $scope, que você irá ligar com

todas as suas funções dentro dos controladores específicos. O $scope

se refere ao atual elemento/área do DOM (não, não é o mesmo

que this), e encapsular um escopo inteligente e capaz de manter os

dados e a lógica completamente situados dentro dos elementos. Isso

traz ao JavaScript escopos públicos/privados para o DOM, o que é

fantástico.

O conceito de $scope pode ser assustador no começo, mas é a sua

conexão com o DOM com o servidor (e dados estáticos se você

também os tiver)! A demonstração lhe deu a ideia básica de como

você pode inserir dados no DOM.

Vamos conferir uma estrutura mais representativas em que teremos

hipotéticamente dados recuperados do servidor para mostrar detalhes

do login de usuários. Por agora vou usar dados estáticos, mais a

frente irei lhe mostrar como buscar dados JSON dinâmicos.

Primeiro vamos configurar o JavaScript:

1

2

3

4

5

6

7

8

9

10

11

12

13

var myApp = angular.module('myApp', []);

myApp.controller('UserCtrl', ['$scope', function ($scope) {

//Criando o namespace user details

//Que nos ajudará no visual do DOM

$scope.user = {};

$scope.user.details = {

"username": "Todd Motto",

"id": "89101112"

};

}]);

Agora portando isso para o DOM para mostrarmos

estes dados:

1

2

3

4

5

6

<div ng-app="myApp">

<div ng-controller="UserCtrl">

<p class="username">Bem-vindo, {{ user.details.username }}</p>

<p class="id">ID do usuário: {{ user.details.id }} </p>

</div>

</div>

Resultado: http://jsfiddle.net/eo_op/xJdWk/

Page 5: Guia definitivo para aprender AngularJs em um dia

É importante lembrar que os Controladores são para dados somente,

e funções (funções de evento também) que conversem com o servidor

e insiram/busquem dados JSON. Manipulação DOM não deve ser

feita aqui, então deixe seu kit jQuery de fora. Diretivas são para

manipulação do DOM, e será o próximo tópico.

Dica profissional: por toda a documentação do Angular (até o

momento que escrevo isso), seus exemplos mostram essa forma de

se criar Controladores:

1

2

3

4

5

var myApp = angular.module('myApp', []);

function MainCtrl ($scope) {

//...

}

… NÃO FAÇA ISSO!!! Isto expõem todas as suas funções no escopo

global e não as deixam ligadas de uma boa maneira com sua

aplicação. Também faz com que você não consiga minificar seu

código ou faça testes facilmente. Não polua o namespace global e

deixe os controladores DENTRO de sua aplicação.

Diretivas

Uma diretiva (confira meu post em Diretivas a partir de scripts/plugins

existentes) em sua forma mais simples é um pequeno pedaço de

HTML modelado, preferencialemente usado múltiplas vezes durante a

aplicação onde é necessária. É uma maneira simples de inetar o DOM

na sua aplicação sem nenhum esforço, realizando interações DOM

personalizadas. Diretivas não são simples no entando, há uma incrível

curva de aprendizado para conquistá-las totalmente, porém a próxima

etapa irá deixá-lo pronto para começar.

Então para o quê as diretivas são usadas? Vários coisas, incluir

componentes DOM, por exemplo abas ou elementos de navegação –

realmente depende do que sua aplicação faz uso da interface do

usuário (UI – User Interface). Se você já brincou com ng-show ou ng-

hide, elas são diretivas (embora não injetem no DOM).

Para este exercício, irei deixar isso realmente simples e criar um tipo

de botão customizado (chamado customButton) que injeta alguma

marcação que eu odeio do ter que ficar escrevendo. Há várias

Page 6: Guia definitivo para aprender AngularJs em um dia

maneiras de definir Diretivas no DOM, elas podem se parecer com

isso:

1

2

3

4

5

6

7

8

9

10

11

<!-- 1: como uma declaração de atributo -->

<a custom-button>Click me</a>

<!-- 2: como um elemento personalizado -->

<custom-button>Click me</custom-button>

<!-- 3: como uma classe (usado para compatibilização nos IE antigos) -->

<a class="custom-button">Click me</a>

<!-- 4: como um comentário (não é boa para este exemplo, entretanto) -->

<!-- directive: custom-button -->

Eu prefiro usá-las como um atributo, elementos customizados estão

vindo no futuro do HTML5 junto com Web Components, mas os

relatórios do Angular com eles mostram vários erros em navegadores

antigos.

Agora que você sabe como declarar e onde as Diretivas são

usadas/injetadas, vamos criar o botão personalizado. Novamente, eu

vou ligar o namespace global da minha aplicação como myApp, sendo

esta a diretiva na sua forma mais simples:

1

2

3

4

5

6

7

myApp.directive('customButton', function () {

return {

link: function (scope, element, attrs) {

// Manipulação e Eventos no DOM aqui!

}

};

});

Eu defini minha diretiva usando o método.directive(), e a chamei

„customButton‟. Quando você capitaliza uma letra no nome da diretiva,

ela deve ser separada com hífen no DOM (como mostrado acima).

Uma diretiva simplesmente retorna a si mesma como um objeto

(Object) e assume um número de parâmetros. O mais importante para

mim, de se dominar primeiro é,restrict, replace, transclude, template e

templateUrl, e para nós a propriedade link. Vamos adicionar as outras

propriedades:

Page 7: Guia definitivo para aprender AngularJs em um dia

1

2

3

4

5

6

7

8

9

10

11

12

13

myApp.directive('customButton', function () {

return {

restrict: 'A',

replace: true,

transclude: true,

template: '<a class="myawesomebutton">' +

'<i class="icon-ok-sign"></i>' +

'</a>',

link: function (scope, element, attrs) {

// Manipulação e Eventos DOM aqui!

}

};

});

Resultado: http://jsfiddle.net/toddmotto/VC4H2/light/

Inspecione o elemento e veja as marcações adicionais que foram

injetadas. Sim, eu sei, não há icone incluso por que eu não inclui o

„Font Awesome‟, mas você viu como funciona. Agora vamos para as

explicações das propriedades das Diretivas:

restrict: isso remonta a utilização, como iremos restringir o uso dos

elementos? Se você estiver usando um projeto que necessite dar

suporte ao IE legado, você provavelmente precisará de declarações

de atributos/classes. Restringindo com „A‟ significa que você restringiu

isso como atributo. „E‟ para elemento, „C‟ para classe e „M‟ para

comment. Como padrão temos „EA‟. Sim, você pode restringir para

múltiplos casos de uso.

replace: Isto substitui a marcação no DOM que define a diretiva, como

usado no exemplo, você irá notar como o DOM inicial é substituido

com o „template‟ (modelo) da Diretiva.

transclude: Simplificando, usando transclude você permite que

conteúdo existente no DOM seja copiado dentro da diretiva. Você verá

as palavras „”Click me” have “moved”„ dentro da Diretiva quando ela

for renderizada.

template: Um template (como acima) permite que você declare uma

marcação a ser injetada. É uma boa ideia usar isto para minúsculo

pedaços de HTML somente. Templates injetados são todos

compilados pelo Angular, isto significa que você pode declarar as

„handlebar template tags‟ {{ }} dentro deles também para ligação.

templateUrl: Similar ao template, mas mantido em seu próprio arquivo

ou tag script. Você pode fazer isso para especificar um modelo de

Page 8: Guia definitivo para aprender AngularJs em um dia

URL, que você vai querer usar para manipular pedaços de HTML que

requerem manter-se em seu próprio arquivo, somente especificando o

caminho e nome do arquivo, preferencialmente mantidos dentro dos

próprios diretóriostemplates:

1

2

3

4

5

6

myApp.directive('customButton', function () {

return {

templateUrl: 'templates/customButton.html'

// coisas da diretiva...

};

});

E dentro do seu arquivo(nome do arquivo não é sensitivo a todos):

1

2

3

4

<!-- dentro do customButton.html -->

<<a href="" class="myawesomebutton" ng-transclude>

<i class="icon-ok-sign"></i>

</a>

O que é realmente bom em se fazer isso. é que o navegador irá

efetivamentecachear o arquivo HTML, bravo! A outra alternativa que

não utiliza o cache é declarar o template dentro da tag script:

1

2

3

4

5

<script type="text/ng-template" id="customButton.html">

<a href="" class="myawesomebutton" ng-transclude>

<i class="icon-ok-sign"></i>

</a>

</script>

Você irá dizer ao Angular que há um ng-template e irá dar a ele um ID.

O Angular irá então buscar pelo ng-template ou o arquivo *.html, então

seja qual for sua preferência. Eu prefiro criar arquivos *.html por serem

fáceis de lidar, melhorarem o desempenho e manter o DOM muito

limpo, pois você pode acabar com 1 ou 100 diretivas, e irá querer ser

capaz de navegar entre elas facilmente.

Serviços (Services)

Serviços geralmente são um ponto confuso. A partir de experiência e

pesquisa, eles nos dão mais um padrão de projeto estilizado do que

diferenças com mais funcionalidade. Você deve usar os Services para

singletons, e Factories para funções mais complexas como Objetos

Literais e casos de uso mais complicados.

Page 9: Guia definitivo para aprender AngularJs em um dia

Aqui temos um exemplo de Service que multiplica dois números:

1

2

3

4

5

myApp.service('Math', function () {

this.multiply = function (x,y) {

return x * y;

};

});

Você pode então usar um Controlador assim:

1

2

3

4

5

6

7

myApp.controller('MainCtrl', ['$scope', function ($scope) {

var a = 12;

var b = 24;

//saída 288

var result = Math.multiply(a, b);

}]);

Sim, multiplicação é muito fácil e não precisa de um Service, mas você

entendeu a essência.

Quando você criar um Service (ou Factory), você vai precisar de usar

a injeção de dependência para dizer ao Angular que ele precisa ligar

seu novo serviço – caso contrário você terá um erro de complicação e

seu Controlador irá quebrar. Você deve ter notado na uma

parte function ($scope) dentro da declaração do Controlador agora, e

isso é a simples injeção de dependência. Você também irá notar

[„$scope‟] antes da function ($scope), irei voltar nisso mais tarde. Aqui

está como usar injeção de dependência para dizer ao Angular que

você precisa do Service:

1

2

3

4

5

6

7

myApp.controller('MainCtrl', ['$scope', 'Math', function ($scope, Math) {

var a = 12;

var b = 24;

// saída 288

var result = Math.multiply(a, b);

}]);

Page 10: Guia definitivo para aprender AngularJs em um dia

Factories

Vindo dos Services os Factories se tornam mais simples, nós

podemos criar Objetos Literais dentro de um Factory ou simplesmente

fornecer métodos mais profundos:

1

2

3

4

5

6

7

8

9

10

myApp.factory('Server', function () {

return {

get: function (url) {

return $http.get(url);

},

post: function (url) {

return $http.post(url);

}

};

});

Aqui eu estou criando um wrapper(empacotador) para

XMLHttpRequest(XHR) do Angular. Depois da injeção de dependência

dentro do Controlador, o uso é simples:

1

2

3

4

5

6

myApp.controller('MainCtrl', ['$scope', 'Server', function ($scope, Server) {

var jsonGet = 'http://myserver/getURL';

var jsonPost = 'http://myserver/postURL';

Server.get(jsonGet);

Server.post(jsonPost);

}]);

Se você quiser consultar o servidor para mudanças, você pode então

configurar Server.poll(jsonPoll), ou talvez se você estiver usando um

Socket você pode configurar Server.socket(jsonSocket). Isso abrirá

portas para você modularizar código assim como criar ferramentas

para você usar e manter o código dentro dos Controladores

minimamente.

Page 11: Guia definitivo para aprender AngularJs em um dia

Filters (Filtros)

Filters são usados em conjunto com arrays de dados e também saídas

de loops. Se você estiver em um loop de dados e quiser filtrar coisas

específicas, você está no lugar certo, você pode também usar os

Filters para filtrar o que um usuário escreveu dentro de um input por

exemplo. Temos algumas formas de user os Filters, dentro dos

Controladores ou como um método definido. Aqui está a utilização por

método, que você pode usar globalmente:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

myApp.filter('reverse', function () {

return function (input, uppercase) {

var out = '';

for (var i = 0; i &lt; input.length; i += 1) {

out = input.charAt(i) + out;

}

if (uppercase) {

out = out.toUpperCase();

}

return out;

}

});

//Controlador incluso para fornecer dados

myApp.controller('MainCtrl', ['$scope', function ($scope) {

$scope.greeting = 'Todd Motto';

}]);

Uso no DOM:

1

2

3

4

5

6

<div ng-app="myApp">

<div ng-controller="MainCtrl">

<p>No filter: {{ greeting }}</p>

<p>Reverse: {{ greeting | reverse }}</p>

</div>

</div>

Saída: http://jsfiddle.net/toddmotto/pmh4s/light/

Utilizando dentro de um ng-repeat:

1

2

3

<ul>

<li ng-repeat="number in myNumbers | filter:oddNumbers">{{ number }}</li>

</ul>

Page 12: Guia definitivo para aprender AngularJs em um dia

E aqui temos um exemplo rápido real de um Filter

dentro de um Controlador:

1

2

3

4

5

6

7

8

9

10

11

12

myApp.controller('MainCtrl', ['$scope', function ($scope) {

$scope.numbers = [10, 25, 35, 45, 60, 80, 100];

$scope.lowerBound = 42;

//Fazendo os Filters

$scope.greaterThanNum = function (item) {

return item > $scope.lowerBound;

};

}]);

E seu uso dentro de um ng-repeat:

1

2

3

<li ng-repeat="number in numbers | filter:greaterThanNum">

{{ number }}

</li>

Saída: http://jsfiddle.net/toddmotto/cZbCf/light/

Essa é a parte principal atrás do AngularJS e sua API, mas estamos

apenas na parte rasa sobre o assunto, porém isso já é mais que

suficiente para você começar a construir sua aplicação com Angular.

Two-way data-binding (Duas vias de

ligação de dados)

Quando eu ouvi sobre two-way data-binding (duas vias para ligação

de dados), eu não entendi realmente o que isso seria. Two-way data-

binding é melhor descrita como um ciclo completo de sincronismo de

dados: atualiza o Model e atualiza o View, atualiza o View e atualiza o

Model. Isso significa que o dado se mantém sincronizado sem precisar

de exageros. Se eu ligar um ng-model com um input e começar a

escrever, isso criará (ou atualizará se já existente) um modelo ao

mesmo tempo.

Page 13: Guia definitivo para aprender AngularJs em um dia

Aqui eu criei um input e o liguei ao modelo chamado „myModel‟, assim

eu posso então usar a sintaxe de chaves para refletir este modelo e

ele será atualizado no View no mesmo momento:

1

2

3

4

5

6

<div ng-app="myApp">

<div ng-controller="MainCtrl">

<input type="text" ng-model="myModel" placeholder="Start typing...">

<p>Meu modelo de dado: {{ myModel }}</p>

</div>

</div>

1

2

3

4

5

myApp.controller('MainCtrl', ['$scope', function ($scope) {

//Captura o modelo de dado

//e/ou inicializa-o com a string existente

$scope.myModel = '';

}]);

Resultado: http://jsfiddle.net/toddmotto/qrr3q/light/

XHR/Ajax/$http chamadas e ligação

JSON

Você pegou a ideia quando começamos a inserir dados para o

$scope, e uma noção superficial de como os Models e two-way data-

binding funcionam, então agora é hora de simular alguma chamada

XHR real com um servidor. Para websites, isto não é necessário se

você tiver uma requisição Ajax específica, isso é principalmente

focado em levar dados para uma aplicação web.

Quando você está desenvolvendo localmente, você possivelmente

está usando algo como Java, ASP, .NET, PHP ou qualquer outra coisa

que rode em um servidor local. Se você estiver se comunicando com

um banco de dados local ou realmente usando o servidor como uma

API para comunicar-se com outro recurso, usaremos a mesma

configuração.

Page 14: Guia definitivo para aprender AngularJs em um dia

Digite „dollar http‟. Seu melhor amigo a partir de agora. O método $http

é um belo wrapper do Angular para acessar dados do servidor, e de

tão fácil você pode fazer isso de olhos fechados. Aqui temos um

simples exemplo de uma requisição „GET‟, que (você adivinhou) pega

dados vindos do servidor. Sua sintaxe é muito parecida com jQuery

por isso sua transição será bem suave:

1

2

3

4

5

6

myApp.controller('MainCtrl', ['$scope', function ($scope) {

$http({

method: 'GET',

url: '//localhost:9000/someurl'

});

}]);

O Angular então retorna algo chamado promise, que é uma maneira

muito mais eficiente e legível de manusear os callbacks. Promises são

encadeados nas funções em que são iniciados a partir da notação por

ponto myPromise(). Como experado, nós recebemos respostas de

erro ou sucesso.

1

2

3

4

5

6

7

8

9

10

11

12

myApp.controller('MainCtrl', ['$scope', function ($scope) {

$http ({

method: 'GET',

url: '//localhost:9000/someUrl'

})

.sucess (function (data, status, headers, config) {

//recuperação de dados bem sucedida

})

.error (function (data, status, headers, config) {

//alguma erro ocorreu :(

});

}]);

Muito bom e legível. Aqui é onde nós fundimos a View com o servidor

pela ligação a um Model ou atualizamos os dados do Model no DOM.

Vamos assumir uma configuração e enviar um username ao DOM, via

uma chamada Ajax.

Idealmente, nós devemos configurar primeiro um modelo para nosso

JSON, que será transportado quando nós ligarmos nossos dados.

Vamos deixá-lo simples, isso será como um „cara do back-end‟ irá

configurar como uma API irá alimentar sua aplicação, sendo por você

esperado o seguinte:

1

2

3

4

5

6

{

"user": {

"name": "Todd Motto",

"id": "80138731"

}

}

Page 15: Guia definitivo para aprender AngularJs em um dia

Isso significa que iremos receber um Objeto retornado do servidor

(com um apelido que chamaremos „dado‟ [você verá que o dado é

passado dentro dos nossos manuseadores promise]), e temos que

entrar em dado.usuarioPropriedade. Dentro de

dado.usuarioPropriedade, nós temos name e id. Acessá-los é fácil,

nós precisamos de procurar por data.user.name que nós retornará

„Todd Motto‟. Agora vamos buscar isso!

O JavaScript (cheque as notações para saber o que está

acontecendo aqui):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

myApp.controller ('UserCtrl', ['$scope', function ($scope) {

//crie um Objeto user

$scope.user = {};

//Inicialize um modelo como uma string vazia

$scope.user.name = '';

//Nós precisamos fazer uma chamada e um get

//o nome do usuário

$http ({

method: 'GET',

url: '//localhost:9000/someUrlForGettingUsername'

})

.sucess (function (data, status, headers, config) {

//Veja aqui, nós estamos agora atribuindo este username

//ao nosso Model existente!

$scope.user.username = data.user.name;

})

.error (function (data, status, headers, config) {

// algum erro aconteceu :(

});

}]);

E agora no DOM, nós podemos fazer o seguinte:

1

2

3

<div ng-controller="UserCtrl">

<p>{{ user.username }}</p>

</div>

Isso irá imprimir o username. Agora nós vamos ir além para entender

“declarative data-binding” (ligação de dados declarativos) que é onde

as coisas ficam realmente empolgantes.

Page 16: Guia definitivo para aprender AngularJs em um dia

Declarative Data-Binding (Ligação de

Dados Declarativos)

A filosofia do Angular é criar HTML dinâmico que seja rico em

funcionalidade e faça muitos trabalhos perfeitamente que você nunca

experaria no lado do cliente da web. Isto é exatamente o que eles

entregam. Vamos imaginar que nós fizemos uma requisição Ajax para

pegar uma lista de emails e sua linha Assunto, dados foram enviados

e nós queremos renderizá-los no DOM. Ai é onde os queixos caem

diante o poder do Angular. Primeiro nós vamos precisar de configurar

um Controlador para Emails:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

myApp.controller ('EmailCtrl', ['$scope', function ($scope) {

// crie um Objeto emails

$scope.emails = {};

// simulando dados que nós iremos receber de volta do servidor

// este é um ARRAY de OBJETOS

$scope.emails.messages = [{

"from": "Steve Jobs",

"subject": "I think I'm holding my phone wrong :/,

"sent": "2013-10-01T08:05:59Z"

},{

"from": "Ellie Goulding",

"subject": "I've got Starry Eyes, lulz",

"sent": "2013-09-21T19:45:00Z"

},{

"from": "Michael Stipe",

"subject": "Everybody hurts, sometimes.",

"sent": "2013-09-12T11:38:30Z"

},{

"from": "Jeremy Clarkson",

"subject": "Think I've found the best car... In the world",

"sent": "2013-09-03T13:15:11Z"

}];

}]);

Agora precisamos conectar isso dentro do nosso HTML. Aqui é onde

nós vamos usar as ligações declarativas (declarative binding) para

declarar o que a aplicação irá fazer para criar nosso primeiro pedaço

de HTML dinâmico. Vamos usar a diretiva do Angular ng-

repeat embutida, que vai iterar sobre os dados e renderizar uma saída

sem absolutamente nenhum callback ou mudanã de estado, é tudo de

graça:

Page 17: Guia definitivo para aprender AngularJs em um dia

1

2

3

4

5

6

7

<ul>

<li ng-repeat="message in emails.messages">

<p>From: {{ message.from }}</p>

<p>Subject: {{ message.subject }}</p>

<p>{{ message.sent | date:'MMM d, y h:mm:ss a' }}</p>

</li>

</ul>

Resultado: http://jsfiddle.net/toddmotto/TAVQc/light/

Eu também coloquei sorrateiramente um filtro de dados (data

filter) para você poder ver como renderizar datas no padrão UTC.

Aprofunde na suite de diretivas ng-* do Angular para liberar todo o

poder das ligações declarativas, pois lhe mostra como juntar os pontos

do servidor do Model ao View e renderizar dados.

Funções de Escopo

Como continuação das ligações declarativas, funções de escopo são o

próximo nível na criação de uma aplicação com alguma

funcionalidade. Aqui temos uma função básica de deletar um de

nossos dados no email:

1

2

3

4

5

myApp.controller ('MainCtrl', ['$scope', function ($scope) {

$scope.deleteEmail = function (index) {

$scope.emails.messages.splice (index, 1)

};

}]);

Dica profissional:É importante pensar sobre deletar dados do Model.

Você não está deletando elementos ou outra coisa real relacionada ao

DOM, Angular é um framework MVC e vai manusear tudo isto para

você com sua “two-way binding” (ligação de duas vias) e o mundo livre

de callback, você somente precisa configurar seu código de forma

inteligente para deixá-lo responder aos seus dados.

Ligar funções ao escopo também ocorre através das Diretivas ng-*,

agora usaremos a Diretiva ng-click:

1 <a>Delete Email</a>

Esta é uma forma diferente para os manipuladores de click inline, por

várias razões. Esse assunto será abordado em breve. Você vai ver

Page 18: Guia definitivo para aprender AngularJs em um dia

que eu também estou passando o $index, e o Angular reconhece o

item que você quer deletar (quanto código e quanta lógica salvas pra

você!).

Resultado (delete alguns

emails!): http://jsfiddle.net/toddmotto/BgZmt/light/

Métodos DOM Declarativos

Agora nós vamos entrar nos métodos DOM, eles são Diretivas e

simulam funcionalidades no DOM que você tem normalmente que

escrever mais códigos e lógicas para tal. Um grande exemplo disto

pode ser um simples navegador que alterna (toggle). Usando ng-show

e um simples ng-click configurados, nós podemos criar um perfeito

“toggling nav”:

1

2

3

4

5

6

<a href="" ng-click="toggle = !toggle">Toggle Nav</a>

<ul ng-show="toggle">

<li>Link 1</li>

<li>Link 2</li>

<li>Link 3</li>

</ul>

Aqui é onde entramos com MVVM, você irá notar que não um

Controlador sendo introduzido aqui, nós entraremos nesta questão do

MVVM em breve.

Resultado (vamos alternar!): http://jsfiddle.net/toddmotto/ZUyW5/light/

Expressões

Uma das minhas partes favoritas do Angular, a qual você usualmente

usa JavaScript para fazer e escreve muito código repetitivo.

Você já fez isso?

1

2

3

4

5

6

7

elem.onclick = function (data) {

if (data.length === 0) {

otherElem.innerHTML = "Sem dados";

} else {

otherElem.innerHTML = "Meus dados";

}

};

Isso pode ser potencialmente um callback vindo de uma requisição

GET, e você vai alterar o DOM baseado no estado do dado. Angular

Page 19: Guia definitivo para aprender AngularJs em um dia

lhe dá isso gratuitamente também, e você será capaz de fazer isto

inline sem escrever qualquer código JavaScript!

1 <p>{{ data.length > 0 && 'Meus dados' || 'Sem dados' }}</p>

Isto irá atualizar a si mesmo dinamicamente sem callbacks como suas

aplicações com polls/fetches de dados. Se não tiver dados, ele lhe dirá

– se tiver dados, também. Temos muitos casos de uso para isso e o

Angular manuseia todos automaticamente via „two-way binding‟

(ligação de duas vias) magicamente.

Resultado : http://jsfiddle.net/eo_op/yPcwt/5/

Exibições Dinâmicas e Roteamento

A filosofia por trás das aplicações single-page (e também websites!).

Você tem um header (cabeçalho), footer (rodapé), sidebar (barra

lateral) e o conteúdo no meio magicamente injeta um novo conteúdo

baseado na sua URL.

O Angular torna esta configuração leve de ser feita, o que chamamos

de exibições dinâmicas. Exibições dinâmicas injetam Views

específicas baseado no URL, através do $routeProvider. Uma simples

configuração:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

myApp.config (['$routeProvider', function ($routeProvider) {

/**

* $routeProvider

*/

$routeProvider

.when ('/', {

templateUrl: 'views/main.html'

})

.otherwise ({

redirectTo: '/'

});

}]);

Page 20: Guia definitivo para aprender AngularJs em um dia

Você verá que „when‟ (quando) a URL é „/‟ (i.e. a raiz do site), você irá

querer injetar o main.html. É uma boa ideia chamar sua View inicial

main.html e não index.html pois você já tem uma página index.html na

configuração da sua single page app. Adicionar mais Views baseadas

na sua URL é muito simples:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

myApp.config (['$routeProvider', function ($routeProvider) {

/*

* $routeProvider

*/

$routeProvider

.when ('/', {

templateUrl: 'views/main.html'

})

.when ('/emails', {

templateUrl: 'views/emails.html'

})

.otherwise ({

redirectTo: '/'

});

}]);

Nós podemos então ter emails.html simplesmente carregado com

nosso HTML que gerá nossa lista de email. Você cria uma aplicação

muito sofisticada com pouco esfoço neste ponto.

Há muito mais sobre o serviço $routeProvider que é muito valioso de

se conhecer, mas isto já irá lhe tirar da inércia. Coisas como

interceptadores $http que irão disparar eventos quando uma chamada

Ajax estiver em andamento, onde podemos mostrar alguns „spinners‟

(símbolo de “carregando”) enquanto estamos carregando os novos

dados.

Dados Estáticos Globais

O GMail manuseia muito destes dados iniciais escrevendo JSON

dentro da página (click com o botão direito – Ver Código Fonte). Se

você quiser colocar dados instantaneamentes na sua página, isto irá

acelerar o tempo de renderizãção e o Angular vai iniciar rapidamente.

Quando desenvolvo nosso aplicativos, as tags Java são colocadas no

DOM e quando renderizadas, o dado é mandado para o backend. [Eu

tenho experiência zero com Java, então se você for perguntar isso,

sim você pode usar qualquer linguagem no seu servidor]. Aqui vamos

Page 21: Guia definitivo para aprender AngularJs em um dia

ver como escrever JSON na sua página e então passar isso para um

Controlador para uso de ligação imediata:

1

2

3

4

5

<!-- inside index.html (bottom of page ofc) -->

<script>

window.globalData = {};

globalData.emails = <javaTagHereToGenerateMessages>;

</script>

Minha suposta tag Java vai então renderizar o dado enquanto a

página analisa e o Angular vai renderizar seus emails

instantâneamente. Somente alimente seus dados dentro de um

Controlador:

1

2

3

4

5

6

7

8

myApp.controller ('EmailCtrl', ['$scope', function ($scope) {

$scope.emails = {};

// Atribua os dados iniciais

$scope.emails.messages = globalData.emails;

}]);

Minificação

Vou falar um pouco sobre minificação de código Angular. Você

provavelmente já experimentou um pocuo até este ponto e talvez

passou seu código por um minificador – e talvez encontrou um erro!

Minificar seu código AngularJS é simples, você precisa de especificar

seu conteúdo de injeção de dependências em um array antes da

função:

1

2

3

4

5

6

7

myApp.controller ('MainCtrl',

['$scope', 'Dependency,' 'Service', 'Factory',

function ($scope, Dependency, Service, Factory) {

// código

}]);

Page 22: Guia definitivo para aprender AngularJs em um dia

Uma vez minificado:

1

2

3

4

5

6

7

8

9

10

11

12

13

myApp.controller ('MainCtrl',

['$scope', 'Dependency', 'Service', 'Factory',

function (a,b,c,d) {

// a = $scope

// b = Dependency

// c = Service

// d = Factory

// $scope alias usage

a.someFunction = function () {...};

}]);

Somente lembre-se de manter seus injetores na ordem que aparecem,

ou provavelmente irá causar uma dor de cabeça para você e sua

equipe.

Diferenças entre MVC e MVVM

Estamos fechando o gigantesco artigo sobre AngularJS, e vou

sucintamente cobrir as diferenças do MVC/MVVM que o Angular tanto

se orgulha:

MVC: fala com o Controlador, Mode-View-Controller

MVVM: encapsula ligações de dados declarativas que tecnicamente

conversam entre si. Model-View-View-Model. O Modelo conversa com

o View, e o View pode falar com o Model. A „two way data-binding‟ do

Angular permite que você os mantenha sincronizados sem que você

precise fazer nada. Isto também lhe permite escrever lógica sem um

Controlador!

Um rápido exemplo disto, você pode criar um ng-repeat sem um

Controlador fornecendo dados:

1

2

3

<li ng-repeat="number in [1,2,3,4,5,6,7,8,9]">

{{ number }}

</li>

Para um teste rápido tudo bem, porém eu sempre recomendo um

Controlador quando as coisas se esclarecerem.

Resultado: http://jsfiddle.net/toddmotto/C9GHF/light/

Page 23: Guia definitivo para aprender AngularJs em um dia

HTML Web Components

Você vai provalmente ser apanhado nessa questão, mas o AngularJS

permite que você crie elementos customizados:

1 <myCustomElement></myCustomElement>

Isso realmente leva a web para o futuro do HTML5. O HTML5 intrduziu

os Web Components e o elemento, que o Angular usa hoje em dia.

Web Components compreendem elementos customizáveis

completamente com injeção dinâmica de JavaScript para população

do View e isto é incrivelmente empolgante.

Comentários de Escopo

Eu penso que estes comentários são realmente uma bela adição ao

nosso fluxo de trabalho, em vez de declarar pedaços de HTML com

comentários deste tipo:

1

2

3

4

5

6

7

<!-- header -->

<header>

Stuff

</header>

<!-- /header -->

Quando introduzimos o Angular, comece a pensar sobre Views e

Escopos, não o DOM! Escopos são de fato fechados, ou seja, a

menos que você deliberadamente compartilhe os dados entre os

controladores, seu dado está inacessível em outros lugares. Eu

estabeleço minhas áreas de escopo e isso vem a ser uma real ajuda.

1

2

3

4

5

<!-- scope: MainCtrl -->

<div class="content" ng-controller="MainCtrl">

</div>

<!-- /scope: MainCtrl -->

Debugando o AngularJS

Temos uma incrível extensão no Chrome que os garotos da Google

recomendam para desenvolvimento e debugging (depuração) com o

Angular, é chamada de Batarang e você pode pegá-la aqui

Leitura Adicional - Aprenda Como criar sua própria Diretiva a partir de um script customizado ou plugin.