.NET

23 mai, 2016

ASP .NET – Single Page Application(SPA) usando AngularJS com Web API – Parte 04

Publicidade

Neste artigo vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: definindo o routing.

Na terceira parte do artigo, criamos a nossa aplicação Angular definindo o module, o controller e usando o serviço $http para obter informações do nosso banco de dados, exibindo-os na view Index.cshtml.

Um recurso muito poderoso do angular é o roteamento de páginas. O módulo ngRoute do Angular fornece serviços para realizar o roteamento de páginas para alguma rota pré-definida. Este recurso está disponível como um arquivo chamado angular-route.js, separado do pacote angular.js.

Para usar o recurso, basta referenciar o arquivo angular-route.js e registrar o ngRoute no módulo da aplicação Angular.

Nota: Você pode baixar o arquivo angular-route.js neste link (podemos instalar o pacote via Nuget).

   angular.module(“nomeModulo”,[“ngRoute”]);

Depois, basta configurar a rota específica usando o serviço $routeProvider e uma rota padrão, caso nenhuma rota seja encontrada.

O serviço $routeProvider possui dois métodos para fazer isso:

  • when(path, rota)  – define uma rota específica

  • otherwise(path) – define rota padrão

O método when recebe dois parâmetros (path e route):

  • O primeiro parâmetro é o path da rota
  • O segundo parâmetro é o objeto de configuração da rota. É neste momento que definimos qual template e controlador serão injetados.

O método otherwise é utilizado para definir uma rota padrão.

Quando nenhuma rota for encontrada, o AngularJS redirecionará a aplicação para essa rota padrão.

Exemplo:

$routeProvider
        .when('/', { templateUrl: '/views/home.html' })
        .when('/artigos', { templateUrl: 'views/artigos.html', controller: 'ArtigosController'})
        .when('/sobre', { templateUrl: 'views/sobre.html', controller: 'SobreController'})
        .otherwise({redirectTo: "/"})

Após isso, para exibir o resultado da renderização das páginas, basta usar a diretiva ng-view na página principal (master page).

<div ng-view> </div>

A figura abaixo mostra um esquema de funcionamento do roteamento no AngularJS:

asp_spaaj41

Para navegar entre as rotas podemos usar links : <a href=”#/produtos”>Produtos</a>

Para redirecionar ou retornar para uma determinada rota, podemos usar:

  • redirectTo : “/produtos”
  • $location.path(“/produtos”)

Onde o serviço $location analisa a URL na barra de endereços do navegador (baseado em window.location) e torna essa URL disponível para a sua aplicação. Alterações na URL na barra de endereços são refletidas no serviço $location e essas mudanças são refletidas na barra de endereços do navegador. ( https://docs.angularjs.org/guide/$location)

Recursos usados:

Nota: Baixe e use a versão Community 2015 do VS. Ela é grátis e é equivalente a versão Professional.

Definindo o roteamento na aplicação Angular

Abra a solução Filmoteca criada no artigo anterior no VS Community 2015 (Open Project). No menu Tools-> Nuget Package Manager, clique em Manage Nuget Packages for Solution. Depois informe o nome angular route e selecione o pacote AngularJS.Route, selecionando o projeto e clicando no botão Install:

asp_spaa41

O pacote javascript angular-route.js será instalado na pasta Scripts do projeto.

Agora temos que incluir a referência a esse pacote em nosso arquivo Index.cshtml na seção scripts:

...
@section scripts
{
    <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-route.js"></script>
    <script src="~/AngularApp/js/filmoteca.js"></script>
    <script src="~/AngularApp/js/listaController.js"></script>
}

Vamos também incluir uma dependência ao roteamento em nosso módulo Angular, incluindo no arquivo filmoteca.js da pasta js o código conforme mostrado abaixo:

(function () {
    var app = angular.module('filmoteca', ["ngRoute"]);
}());

Lembre-se que as dependências são informadas como o segundo parâmetro para o método module; onde o parâmetro é um array de strings contendo os nomes dos módulos requeridos.

Para o roteamento o nome é ngRoute.

Agora estamos prontos para definir o roteamento em nossa aplicação Angular usando um método config e o serviço $routeprovider, onde$routeProvider é o provider do serviço $route.

Por se tratar de um provider, ele só pode ser injetado dentro da função config (não podemos utilizar $routeProvider dentro de um controlador).

Abra o arquivo filmoteca.js e inclua o código abaixo neste arquivo:

(function () {
    var app = angular.module("filmoteca", ["ngRoute"]);
    var config = function ($routeProvider) {
        $routeProvider
        .when("/",
               { templateUrl: "/cliente/html/lista.html", controller: "listaController" })
        .when("/detalhes/:id",
               { templateUrl: "/cliente/html/detalhes.html", controller: "detalhesController" })
        .otherwise(
               { redirecTo: "/"});
    };
    app.config(config);
}());

No código acima definimos duas rotas:

  1. para a raiz do projeto (“/”) a rota é : /cliente/html/lista.html
  2. para a url /detalhes/id a rota é : /cliente/html/detalhes.html

Onde estamos acessando os arquivos lista.html e detalhes.html na pasta html dentro da pasta cliente. Vamos, agora, criar a pasta Cliente e dentro dela uma outra pasta html; a seguir, criaremos os arquivos html lista.html e detalhes.html.

Criando os arquivos HTML do roteamento na pasta html e o controller detalhesController

Selecione o projeto e no menu Project clique em New Folder e informe o nome Cliente. A seguir, clique com o botão direito sobre a pasta Cliente e no menu Project clique em New Folder e informe html. Agora clique com o botão direito do mouse sobre a pasta html e a seguir em Add -> New Item. Em seguida selecione o template HTML page e informe o nome lista.html. Inclua o código abaixo neste arquivo:

<div ng-app="filmoteca" ng-controller="listaController">
    <table class="table">
        <tr>
            <th>Título</th>
        </tr>
        <tr ng-repeat="filme in filmes">
            <td>{{filme.Titulo}}</td>
            <td>
                <a href="#/html/detalhes/{{filme.Id}}">Detalhes</a>
            </td>
        </tr>
    </table>
</div>

O código acima usa uma tabela HTML e a diretiva ng-repeat para percorrer o array de filmes que será obtido do banco de dados via WebApi.

A seguir, definimos um link usando a rota detalhes/id de forma que quando o usuário clicar no link será montada a URL: detalhes/id onde id é o código do filme que será passado como um parâmetro.

Repita o procedimento e crie o arquivo detalhes.html com o código a seguir na mesma pasta:

<div ng-controller="detalhesController">
    <h2>
       Filme :  {{filme.Titulo}}
    </h2>
    <div>
       <h3> Lançamento em : {{filme.AnoLancamento}} </h3>
    </div>
    <div>
       <h3>{{filme.Duracao}} minutos de duração.</h3>
    </div>
    <hr />
    <a href="#/">Lista</a>
</div>

Perceba que o controller usado na página html é o controle detalhesController que teremos que definir na pasta js.

Clique, então, com o botão direito do mouse sobre a pasta js e a seguir em Add-> New Item.

Selecione o template JavaScript file e informe o nome detalhesController.js, incluindo, a seguir, o código abaixo neste arquivo:

(function (app) {
    var detalhesController = function ($scope, $http, $routeParams)
    {
        var id = $routeParams.id;
        $http.get("/api/filme/" + id)
        .success(function (data) {
            $scope.filme = data;
        });
    };
    app.controller("detalhesController", detalhesController)
}(angular.module("filmoteca")));

Este controlador utiliza dois serviços: o serviço $routeParams e o serviço $http.

O serviço $routeParams contém os parâmetros adquiridos a partir da URL, como o valor para o Id do filme. Obtendo o Id e combinando-o com a URL, permite-se que o serviço $http retorne os detalhes atualizados para o filme específico e coloque os dados no objeto $scope para posterior apresentação na view.

Vamos ajustar agora a view Index.cshtml na pasta Views/Home substituindo o código existente pelo código abaixo:

<div class="well">
    <h4>Macoratti .net</h4>
</div>
<div data-ng-app="filmoteca">
    <ng-view></ng-view>
</div>

@section scripts
{
    <script src="~/Scripts/angular.js"></script>
    <script src="~/Scripts/angular-route.js"></script>
    <script src="~/AngularApp/js/filmoteca.js"></script>
    <script src="~/AngularApp/js/listaController.js"></script>
    <script src="~/AngularApp/js/detalhesController.js"></script>
}

No código acima incluímos a diretiva ng-view para renderizar as páginas html definidas no roteamento e a referência ao controllerdetalhesController.js criado.

Executando o projeto, iremos obter o seguinte resultado:

asp_spaa42

Note que o link Detalhes monta a url : #/detalhes/id. Clicando em qualquer um dos links iremos obter os detalhes do filme especificado pelo id:

asp_spaa43

Poderíamos implementar aqui a edição dos dados, mas antes de prosseguir com essa tarefa vamos incrementar o nosso projeto acrescentando uma abstração ao serviço $http para tornar a interação com a Web API mais fácil.

Na próxima parte do artigo vamos criar um serviço customizado para encapsular os recursos da Web API FilmeController de forma a não termos que usar o serviço $http diretamente dos controllers.

Pegue o projeto até esta etapa aqui: Filmoteca4.zip (sem as referências)