Neste artigo, vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: criando a aplicação Angular.
Na segunda parte do artigo, criamos a nossa Web API e agora vamos partir para o desenvolvimento do lado do cliente com AngulaJS.
O AngularJS é um framework JavaScript open source, mantido pelo Google, que auxilia na execução de single-page applications. Seu objetivo é aumentar aplicativos que podem ser acessados por um navegador web, sob o padrão model–view–controller (MVC), em um esforço para facilitar tanto o desenvolvimento quanto o teste dos aplicativos.
A biblioteca lê o HTML que contém tags especiais e então executa a diretiva à qual essa tag pertence, e faz a ligação entre a apresentação e seu modelo, representado por variáveis JavaScript comuns. O valor dessas variáveis JavaScript podem ser setadas manualmente, ou via um recurso JSON estático ou dinâmico.
Um documento usando AngularJS é composto basicamente das seguintes partes:
- Declaração da biblioteca AngularJS
- Declaração das diretivas AngularJS
- Utilização de código CSS
- Código JavaScript
É importante ressaltar que o foco do framework AngularJS está no cliente.
Precisamos então criar uma aplicação Angular definindo o módulo inicial. Um Module no Angular é uma abstração que permite agrupar vários componentes mantendo-os isolados de outros componentes e código em uma aplicação. Esse isolamento torna mais fácil realizar os testes de unidade.
Vários recursos do Angular são organizados em diferentes Modules que vamos precisar para nossa aplicação.
Mas, antes de iniciar, vamos organizar o nosso projeto preparando-o para a criação da aplicação Angular e do código que iremos usar.
Recursos usados:
- Visual Studio 2015 Community
- AngularJS
- Web API
- Entity Framework
Nota: Baixe e use a versão Community 2015 do VS; ela é grátis e é equivalente à versão Professional.
Definindo a aplicação Angular: Module, Controller e Service
Abra a solução Filmoteca criada no artigo anterior no VS Community 2015 (Open Project).
Vamos criar uma nova pasta no projeto chamada AngularApp (você pode usar outro nome qualquer, como App, Cliente etc.).
Selecione o projeto Filmoteca e, no menu Project, clique em New Folder e informe o nome AngularApp.
A seguir, selecione a pasta AngularApp e clique com o botão direito do mouse. Depois, clique em Add-> New Folder e informe o nome js.
Em seguida, selecione a pasta js, clique com o botão direito do mouse e clique em Add-> New Item.
Selecione o template JavaScript File, informe o nome filmoteca.js e clique no botão Add.
Dessa forma, teremos o arquivo javascript filmoteca.js criado na pasta /AngularApp/js:
A seguir, vamos criar uma aplicação Angular definindo um module e depois um controller.
A aplicação Angular possui o código abaixo no arquivo filmoteca.js:
(function () { var app = angular.module('filmoteca', []); }());
A variável angular é uma variável global e expõe a API do Angular.
Usamos a função module para criar um novo módulo chamado ‘filmoteca’, no qual o segundo parâmetro, o array vazio [], declara as dependências para o módulo. No nosso caso, o módulo não possui dependências ainda.
Em seguida, vamos criar um controller para nossa aplicação Angular para exibir uma lista de filmes.
Os controllers do Angular são objetos que usamos para governar a seção do DOM e definir o model a ser exibido na view. Eles possuem estado e seu tempo de vida está associado ao DOM onde os dados são exibidos.
Nota: Os controllers do Angular são diferentes dos controllers da aplicação ASP .NET MVC que apenas processam uma requisição e não mantêm estado.
Na pasta js, inclua um novo arquivo javascript chamado listaController.js com o seguinte código:
(function (app) { var listaController = function () { }; app.controller('listaController',listaController); } (angular.module("filmoteca",[])))
O código usa novamente angular.module, mas não para criar um módulo e sim para obter uma referência ao módulo existente chamado ‘filmoteca’ que criamos no arquivo filmoteca.js. O código passa a referência do módulo para a função como uma variável chamada app.
Temos aqui uma função listaController definida como um construtor que realiza a chamada ao método controller do módulo da aplicação.
O primeiro parâmetro é o nome do controller (o Angular procura pelo controller usando esse nome), e o segundo parâmetro é o construtor associado ao nome.
Até o momento, o controller não está realizando nenhuma tarefa, mas já podemos referenciar o arquivo listaController.js em nosso projeto, juntamente com a biblioteca do Angular e o arquivo filmoteca.js.
Vamos abrir o arquivo _Layout.cshtml da pasta /Views/Shared e definir o código abaixo nessa view:
<div class="jumbotron"> <h4>Macoratti .net</h4> </div> <div ng-app="filmoteca" ng-controller="listaController"> </div> @section scripts { <script src="~/Scripts/angular.js"></script> <script src="~/AngularApp/js/filmoteca.js"></script> <script src="~/AngularApp/js/listaController.js"></script> }
Nota: Poderíamos fazer essa definição no arquivo _Layout.cshtml ou ainda no arquivo BundleConfig.cs.
A diretiva ng-app define a aplicação Angular carregando o module ‘filmoteca’ vinculado à div na aplicação.
A diretiva ng-controller vincula o controlador ‘listaController’ à mesma div, de forma que todo código no interior dessa div será renderizado pelo AngularJS.
O controller é responsável pela definição das regras de negócio e pela definição do model e das informações que serão exibidas na view.
Para fazer com que nosso controlador possa acessar os dados em nosso exemplo, teremos que usar os serviços do angular.
Service ou Serviço no Angular são objetos que realizam uma tarefa específica, como se comunicar via HTTP com um servidor, gerenciar o histórico do navegador, realizar a localização, implementar a compilação do DOM etc. Os services como os controllers são registrados em um module pelo Angular.
O serviço que iremos usar e que o Angular disponibiliza é o serviço $http, que expõe métodos para realizar requisições HTTP assíncronas.
No nosso exemplo, o controlador vai precisar usar esse serviço ($http) para realizar chamadas ao servidor e se comunicar com a Web API, e assim obter as informações do nosso banco de dados.
Vamos então alterar o nosso controlador definido em listaController.js com o código abaixo:
(function (app) { var listaController = function ($scope, $http) { $http.get("/api/filme") .success(function (data) { $scope.filmes = data; }); }; app.controller("listaController", listaController) }(angular.module("filmoteca", [])))
Nesse código, estamos registrando o serviço $http no controlador. Esse serviço possui uma API que inclui métodos como get,post, put e delete, e cada um desses métodos mapeia para o correspondente verbo HTTP com o mesmo nome. Assim, o código acima está enviando uma requisição GET para a Url /api/filme. O retorno é um objeto promisse que oferece uma alternativa às funções callback.
Objetos promisse fazem o que o seu nome diz: prometem enviar um resultado futuro, e o Angular usa esses objetos para as requisições assíncronas aplicando o método sucess do promisse para registrar o código que você deseja executar quando o promisse estiver completado com sucesso.
O código acima usa o objeto promisse para registrar um manipulador success que define os dados retornados do servidor (uma coleção de filmes) para o objeto $scope e, assim, ficar disponível para ser exibido na view.
Para obter o resultado e exibi-lo na view, basta incluir no arquivo Index.cshtml o código abaixo:
<div class="jumbotron"> <h4>Macoratti .net</h4> </div> <div ng-app="filmoteca" ng-controller="listaController"> {{filmes}} </div> @section scripts { <script src="~/Scripts/angular.js"></script> <script src="~/AngularApp/js/filmoteca.js"></script> <script src="~/AngularApp/js/listaController.js"></script> }
A diretiva de vinculação {{filmes}} obtém o valor do objeto filmes obtido via serviço $http e disponibilizado na variável $scope.filmes do controlador listaController.
Executando o projeto iremos obter:
Podemos melhorar a apresentação usando a diretiva ng-repeat e alguns recursos do bootstrap definindo o código a seguir:
<div class="jumbotron"> <h4>Macoratti .net</h4> </div> <div ng-app="filmoteca" ng-controller="listaController"> <table class="table"> <tr> <th>Título</th> <th>Ano de Lançamento</th> <th>Duração (min.)</th> </tr> <tr ng-repeat="filme in filmes"> <td>{{filme.Titulo}}</td> <td>{{filme.AnoLancamento}}</td> <td>{{filme.Duracao}}</td> </tr> </table> </div> @section scripts { <script src="~/Scripts/angular.js"></script> <script src="~/AngularApp/js/filmoteca.js"></script> <script src="~/AngularApp/js/listaController.js"></script> }
Executando novamente teremos:
Muito melhor, não é mesmo?
Podemos melhorar ainda mais e, se quisermos criar uma aplicação Single Page Application(SPA) funcional, teremos que usar o recurso do roteamento do Angular.
Na próxima parte do artigo, veremos o Routing do Angular e como ele pode nos ajudar a criar aplicações SPA funcionais.