AngularJS é uma estrutura JavaScript MVC desenvolvida pelo Google que permite criar aplicativos front-end bem estruturados, facilmente testáveis e de manutenção.
Se você ainda não experimentou o AngularJS, está perdendo. A estrutura consiste em um conjunto de ferramentas totalmente integrado que o ajudará a construir aplicativos do lado do cliente ricos e bem estruturados de forma modular - com menos código e mais flexibilidade.
AngularJS estende HTML, fornecendo diretivas que adicionam funcionalidade à sua marcação e permitem criar modelos dinâmicos poderosos. Você também pode criar suas próprias diretivas, elaborando componentes reutilizáveis que atendem às suas necessidades e abstraindo toda a lógica de manipulação do DOM.
Ele também implementa vinculação de dados bidirecional, conectando seu HTML (visualizações) a seus objetos JavaScript (modelos) perfeitamente. Em termos simples, isso significa que qualquer atualização em seu modelo será imediatamente refletida em sua visualização, sem a necessidade de qualquer manipulação DOM ou tratamento de eventos (por exemplo, com jQuery).
Por fim, adoro o Angular por causa de sua flexibilidade em relação à comunicação do servidor. Como a maioria dos frameworks JavaScript MVC, ele permite que você trabalhe com qualquer tecnologia do lado do servidor, desde que possa servir seu aplicativo por meio de uma API da web RESTful. Mas a Angular também oferece serviços em cima de XHR que simplifica drasticamente seu código e permite que você abstraia chamadas de API em serviços reutilizáveis. Como resultado, você pode mover seu modelo e lógica de negócios para o front-end e construir aplicativos da web agnósticos de back-end. Nesta postagem, faremos exatamente isso, uma etapa de cada vez.
Primeiro, vamos decidir a natureza do aplicativo que queremos construir. Neste guia, preferimos não perder muito tempo no back-end, por isso vamos escrever algo com base em dados que podem ser facilmente obtidos na Internet, como um aplicativo de feed de esportes!
como usar temas de bootstrap
Já que sou um grande fã de automobilismo e Fórmula 1, usarei um serviço de API de autosport para atuar como nosso back-end. Felizmente, os caras da Ergast são gentis o suficiente para fornecer uma API de automobilismo gratuita que será perfeita para nós.
Para dar uma olhada no que vamos construir, dê uma olhada no demonstração ao vivo . Para embelezar a demonstração e mostrar alguns modelos Angular, apliquei um tema Bootstrap de WrapBootstrap , mas visto que este artigo não é sobre CSS, vou apenas abstrair dos exemplos e deixá-lo de fora.
Vamos iniciar nosso aplicativo de exemplo com alguns clichês. Eu recomendo o semente angular projeto, uma vez que não só fornece um ótimo esqueleto para inicialização, mas também define o terreno para testes de unidade com Carma e Jasmim (não faremos nenhum teste nesta demonstração, então vamos apenas deixar isso de lado por enquanto; veja Parte 2 deste tutorial para obter mais informações sobre como configurar seu projeto para testes de unidade e ponta a ponta).
EDITAR (maio de 2014): Desde que escrevi este tutorial, o semente angular projeto passou por algumas mudanças pesadas (incluindo a adição de Bower como gerenciador de pacotes). Se você tiver alguma dúvida sobre como implantar o projeto, dê uma olhada rápida na primeira seção de seu guia de referência . Dentro Parte 2 deste tutorial, Bower , entre outras ferramentas, é abordado com mais detalhes.
OK, agora que clonamos o repositório e instalamos as dependências, o esqueleto do nosso aplicativo ficará assim:
Agora podemos começar a codificar. Como estamos tentando construir um feed de esportes para um campeonato de corrida, vamos começar com a visão mais relevante: a mesa do campeonato .
Dado que já temos uma lista de drivers definida em nosso escopo (pendure comigo - vamos chegar lá) e ignorando qualquer CSS (para facilitar a leitura), nosso HTML pode ser semelhante a:
Drivers Championship Standings {{$index + 1}}
{{driver.Driver.givenName}} {{driver.Driver.familyName}} {{driver.Constructors[0].name}} {{driver.points}}
A primeira coisa que você notará neste modelo é o uso de expressões (“{{“ e “}}”) para retornar valores de variáveis. No desenvolvimento do AngularJS , as expressões permitem que você execute alguns cálculos para retornar um valor desejado. Algumas expressões válidas seriam:
{{ 1 + 1 }}
{ 946757880 }
{{ user.name }}
Efetivamente, as expressões são snippets semelhantes a JavaScript. Mas, apesar de ser muito poderoso, você não deve usar expressões para implementar qualquer lógica de nível superior. Para isso, usamos diretrizes.
A segunda coisa que você notará é a presença de ng-attributes
, que você não veria na marcação típica. Essas são as diretrizes.
Em um alto nível, as diretivas são marcadores (como atributos, tags e nomes de classes) que dizem ao AngularJS para anexar um determinado comportamento a um elemento DOM (ou transformá-lo, substituí-lo etc.). Vamos dar uma olhada nos que já vimos:
O ng-app
diretiva é responsável por inicializar seu aplicativo definindo seu escopo. No AngularJS, você pode ter vários aplicativos na mesma página, portanto, essa diretiva define onde cada aplicativo distinto começa e termina.
O ng-controller
A diretiva define qual controlador estará encarregado de sua visualização. Nesse caso, denotamos o driversController
, que fornecerá nossa lista de drivers (driversList
).
folha de referências de css com exemplos
O ng-repeat
A diretiva é uma das mais comumente usadas e serve para definir o escopo do modelo ao fazer um loop pelas coleções. No exemplo acima, ele replica uma linha na tabela para cada driver em driversList
.
Claro, não há uso para nossa visualização sem um controlador. Vamos adicionar driversController
para o nosso controllers.js:
angular.module('F1FeederApp.controllers', []). controller('driversController', function($scope) { $scope.driversList = [ { Driver: { givenName: 'Sebastian', familyName: 'Vettel' }, points: 322, nationality: 'German', Constructors: [ {name: 'Red Bull'} ] }, { Driver: { givenName: 'Fernando', familyName: 'Alonso' }, points: 207, nationality: 'Spanish', Constructors: [ {name: 'Ferrari'} ] } ]; });
Você deve ter notado o $scope
variável que estamos passando como um parâmetro para o controlador. O $scope
A variável deve ligar seu controlador e visualizações. Em particular, ele contém todos os dados que serão usados em seu modelo. Qualquer coisa que você adicionar a ele (como driversList
no exemplo acima) estará diretamente acessível em suas visualizações. Por enquanto, vamos apenas trabalhar com uma matriz de dados fictícia (estática), que substituiremos mais tarde por nosso serviço de API.
Agora, adicione ao app.js:
angular.module('F1FeederApp', [ 'F1FeederApp.controllers' ]);
Com essa linha de código, inicializamos nosso aplicativo e registramos os módulos dos quais ele depende. Voltaremos a esse arquivo (app.js
) mais tarde.
Agora, vamos colocar tudo junto em index.html
:
F-1 Feeder Drivers Championship Standings {{$index + 1}}
{{driver.Driver.givenName}} {{driver.Driver.familyName}} {{driver.Constructors[0].name}} {{driver.points}}
Modulo pequenos erros, agora você pode inicializar seu aplicativo e verificar sua lista (estática) de drivers.
Nota: Se você precisar de ajuda para depurar seu aplicativo e visualizar seus modelos e escopo no navegador, recomendo dar uma olhada no incrível Batarang plugin para o Chrome.
Uma vez que já sabemos como exibir os dados de nosso controlador em nossa visão, é hora de realmente buscar dados ativos de um servidor RESTful.
Para facilitar a comunicação com servidores HTTP, o AngularJS fornece o $http
e $resource
Serviços. O primeiro é apenas uma camada sobre XMLHttpRequest ou JSONP , enquanto o último fornece um nível mais alto de abstração. Usaremos $http
.
Para abstrair nossas chamadas de API do servidor do controlador, vamos criar nosso próprio serviço personalizado que irá buscar nossos dados e atuar como um wrapper em torno de $http
adicionando isso ao nosso services.js
:
angular.module('F1FeederApp.services', []). factory('ergastAPIservice', function($http) { var ergastAPI = {}; ergastAPI.getDrivers = function() { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK' }); } return ergastAPI; });
Com as duas primeiras linhas, criamos um novo módulo (F1FeederApp.services
) e registramos um serviço dentro desse módulo (ergastAPIservice
). Observe que passamos $http
como parâmetro para esse serviço. Isso diz ao Angular's Injeção de dependência motor que nosso novo serviço requer (ou depende de ) o $http
serviço.
De maneira semelhante, precisamos dizer ao Angular para incluir nosso novo módulo em nosso aplicativo. Vamos registrá-lo com app.js
, substituindo nosso código existente por:
Glass Steagall Act revogar consequências
angular.module('F1FeederApp', [ 'F1FeederApp.controllers', 'F1FeederApp.services' ]);
Agora, tudo o que precisamos fazer é ajustar nosso controller.js
um pouco, inclua ergastAPIservice
como uma dependência, e estaremos prontos para ir:
angular.module('F1FeederApp.controllers', []). controller('driversController', function($scope, ergastAPIservice) { $scope.nameFilter = null; $scope.driversList = []; ergastAPIservice.getDrivers().success(function (response) { //Dig into the responde to get the relevant data $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings; }); });
Agora recarregue o aplicativo e verifique o resultado. Observe que não fizemos nenhuma alteração em nosso modelo, mas adicionamos um nameFilter
variável ao nosso escopo. Vamos colocar essa variável em uso.
Ótimo! Temos um controlador funcional. Mas mostra apenas uma lista de drivers. Vamos adicionar algumas funcionalidades implementando uma entrada de pesquisa de texto simples que filtrará nossa lista. Vamos adicionar a seguinte linha ao nosso index.html
, logo abaixo da tag:
ng-model
Agora estamos utilizando Esta linha informa Nesse ponto, a vinculação de dados bidirecional é ativada: sempre que um valor é inserido no campo de pesquisa, o Angular garante imediatamente que Recarregue o aplicativo e verifique a barra de pesquisa. Observe que este filtro irá procurar a palavra-chave em todos os atributos do modelo, incluindo aqueles que não estamos usando. Digamos que queremos apenas filtrar por Agora, de volta a Recarregue o aplicativo mais uma vez e agora temos uma busca por nome. Nosso próximo objetivo é criar uma página de detalhes do motorista que nos permitirá clicar em cada motorista e ver os detalhes de sua carreira. Primeiro, vamos incluir o Com essa alteração, navegando para O AngularJS permitirá que você vincule suas rotas a controladores e visualizações específicos. Mas primeiro, precisamos dizer ao Angular onde renderizar essas vistas parciais. Para isso, usaremos o Agora, sempre que navegarmos pelas rotas de nosso aplicativo, o Angular carregará a visualização associada e a renderizará no lugar da tag. Tudo o que precisamos fazer é criar um arquivo chamado Finalmente, vamos decidir o que queremos mostrar na página de detalhes. Que tal um resumo de todos os fatos relevantes sobre o motorista (por exemplo, nascimento, nacionalidade) junto com uma tabela contendo seus resultados recentes? Para fazer isso, adicionamos a Desta vez, fornecemos o ID do motorista ao serviço para que possamos recuperar as informações relevantes apenas para um motorista específico. Agora, modificamos O importante a notar aqui é que acabamos de injetar o Agora que temos nossos dados no escopo, precisamos apenas da visualização parcial restante. Vamos criar um arquivo chamado Observe que agora estamos colocando Adicione um monte de CSS e renderize sua página. Você deve acabar com algo assim: Agora você está pronto para iniciar seu aplicativo e certificar-se de que ambas as rotas estão funcionando conforme desejado. Você também pode adicionar um menu estático a EDITAR (maio de 2014): Recebi muitos pedidos de uma versão para download do código que construímos neste tutorial. Portanto, decidi lançá-lo Aqui (sem CSS). No entanto, eu realmente faço não recomendamos baixá-lo, pois este guia contém todas as etapas necessárias para construir o mesmo aplicativo com suas próprias mãos, o que será um exercício de aprendizagem muito mais útil e eficaz. Neste ponto do tutorial, cobrimos tudo que você precisa para escrever um aplicativo simples (como um alimentador de Fórmula 1). Cada uma das páginas restantes na demonstração ao vivo (por exemplo, tabela do campeonato do construtor, detalhes da equipe, calendário) compartilham a mesma estrutura básica e conceitos que analisamos aqui. Por fim, lembre-se de que o Angular é uma estrutura muito poderosa e mal tocamos a superfície em termos de tudo que ela tem a oferecer. Dentro Parte 2 deste tutorial, daremos exemplos de por que o Angular se destaca entre seus frameworks MVC de front-end: testabilidade. Vamos revisar o processo de escrever e executar testes de unidade com Carma , alcançando integração contínua com Yeomen , Terra , e Bower , e outros pontos fortes desta fantástica estrutura de front-end. AngularJS é uma estrutura JavaScript MVC desenvolvida pelo Google que permite criar aplicativos front-end bem estruturados, facilmente testáveis e de manutenção. O AngularJS estende o HTML fornecendo diretivas que adicionam funcionalidade à sua marcação e permitem criar modelos dinâmicos poderosos. Você também pode criar suas próprias diretivas, criar componentes reutilizáveis que atendam às suas necessidades e abstrair toda a lógica de manipulação do DOM.$scope.nameFilter
diretiva. Esta diretiva vincula nosso campo de texto ao ng-repeat
variável e garante que seu valor está sempre atualizado com o valor de entrada. Agora, vamos visitar index.html mais uma vez e fazer um pequeno ajuste na linha que contém diretiva: código python para extrair dados do twitter
ng-repeat
driversList
que, antes de enviar os dados, o nameFilter
array deve ser filtrado pelo valor armazenado em $scope.nameFilter
.nameFilter
que associamos a ele é atualizado com o novo valor. Uma vez que a ligação funciona nos dois sentidos, no momento em que ng-repeat
valor é atualizado, a segunda diretiva associada a ele (ou seja, o Driver.givenName
) também obtém o novo valor e a visualização é atualizada imediatamente.Driver.familyName
e driversController
: Primeiro, adicionamos a $scope.driversList = [];
, logo abaixo de $scope.searchFilter = function (driver) ;
linha:index.html
ng-repeat
, atualizamos a linha que contém diretiva: $routeProvider
Rotas
app.js
serviço (em app.js
) que nos ajudará a lidar com essas rotas de aplicação . Então, vamos adicionar duas dessas rotas: uma para a mesa do campeonato e outra para os detalhes do piloto. Aqui está nosso novo angular.module('F1FeederApp', [ 'F1FeederApp.services', 'F1FeederApp.controllers', 'ngRoute' ]). config(['$routeProvider', function($routeProvider) { $routeProvider. when('/drivers', {templateUrl: 'partials/drivers.html', controller: 'driversController'}). when('/drivers/:id', {templateUrl: 'partials/driver.html', controller: 'driverController'}). otherwise({redirectTo: '/drivers'}); }]);
:http://domain/#/drivers
driversController
irá carregar o partials/drivers.html
e procure a vista parcial para renderizar em ng-view
. Mas espere! Ainda não temos visualizações parciais, certo? Precisamos criá-los também.Vistas Parciais
index.html
, modificando nossa F-1 Feeder
para espelhar o seguinte:sobre o efeito geral das taxas de juros negativas na economia, economistas
partials/drivers.html
e colocar nosso HTML da tabela do campeonato lá. Também usaremos essa chance para vincular o nome do motorista à nossa rota de detalhes do motorista:
Drivers Championship Standings {{$index + 1}} {{driver.Driver.givenName}} {{driver.Driver.familyName}}
{{driver.Constructors[0].name}} {{driver.points}} services.js
angular.module('F1FeederApp.services', []) .factory('ergastAPIservice', function($http) { var ergastAPI = {}; ergastAPI.getDrivers = function() { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK' }); } ergastAPI.getDriverDetails = function(id) { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/driverStandings.json?callback=JSON_CALLBACK' }); } ergastAPI.getDriverRaces = function(id) { return $http({ method: 'JSONP', url: 'http://ergast.com/api/f1/2013/drivers/'+ id +'/results.json?callback=JSON_CALLBACK' }); } return ergastAPI; });
:controllers.js
angular.module('F1FeederApp.controllers', []). /* Drivers controller */ controller('driversController', function($scope, ergastAPIservice) { $scope.nameFilter = null; $scope.driversList = []; $scope.searchFilter = function (driver) re.test(driver.Driver.familyName); ; ergastAPIservice.getDrivers().success(function (response) { //Digging into the response to get the relevant data $scope.driversList = response.MRData.StandingsTable.StandingsLists[0].DriverStandings; }); }). /* Driver controller */ controller('driverController', function($scope, $routeParams, ergastAPIservice) { $scope.id = $routeParams.id; $scope.races = []; $scope.driver = null; ergastAPIservice.getDriverDetails($scope.id).success(function (response) { $scope.driver = response.MRData.StandingsTable.StandingsLists[0].DriverStandings[0]; }); ergastAPIservice.getDriverRaces($scope.id).success(function (response) { $scope.races = response.MRData.RaceTable.Races; }); });
:$routeParams
:id
serviço no controlador de driver. Este serviço nos permitirá acessar nossos parâmetros de URL (para $routeParams.id
, neste caso) usando partials/driver.html
. <- Back to drivers list
e adicione:
{{driver.Driver.givenName}} {{driver.Driver.familyName}} Country: {{driver.Driver.nationality}}
Team: {{driver.Constructors[0].name}}
Birth: {{driver.Driver.dateOfBirth}}
Biography
Formula 1 2013 Results Round Grand Prix Team Grid Race {{race.round}} {{race.raceName}}
{{race.Results[0].Constructor.name}} {{race.Results[0].grid}} {{race.Results[0].position}} ng-show
true
diretiva para um bom uso. Esta diretiva só mostrará o elemento HTML se a expressão fornecida for false
(ou seja, nem null
, nem index.html
). Nesse caso, o avatar só aparecerá depois que o objeto driver for carregado no osciloscópio pelo controlador.Toques finais
|_+_|
para melhorar os recursos de navegação do usuário. As possibilidades são infinitas. Conclusão
Compreender o básico
O que é AngularJS?
Por que AngularJS?