ASP .NET – Single Page Application(SPA) usando AngularJS com Web API – Parte 06
Neste artigo eu vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: criando um serviço.
Neste artigo eu vou mostrar como criar uma aplicação ASP .NET Single Page Application usando os recursos do AngularJS com Web API: criando um serviço.
Na quinta parte do artigo criamos o serviço definido em filmeService de forma que encapsulasse as funcionalidades da nossa Web API representada pelo controller FilmeController.
Neste artigo, vamos implementar as funcionalidades para deletar, editar e criar filmes em nossa aplicação SPA.
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 a versão profissional.
Deletando filmes
Agora vamos permitir que o usuário possa deletar um filme em nossa aplicação. Para isso, abra a solução Filmoteca, criada no artigo anterior no VS Community 2015 (Open Project). Depois abra o arquivo lista.html e inclua a linha de código para incluir um botão de comando, conforme o código a seguir:
<div ng-controller="listaController">
<table class="table">
<tr>
<th>Título</th>
</tr>
<tr ng-repeat="filme in filmes">
<td>{{filme.Titulo}}</td>
<td>
<a class="btn btn-primary" href="#/detalhes/{{filme.Id}}">Detalhes</a>
<button class="btn btn-danger" ng-click="deleta(filme)">Deletar</button>
</td>
</tr>
</table>
</div>
Nossa view lista.html está usando alguns recursos do bootstrap para definir estilos para o button Deletar e para o link Detalhes.
Nesta view, incluímos um button HTML onde temos uma diretiva ng-click que aciona a function deleta(filme), passando o filme associado.
Precisamos, então, alterar o código do controller listaController incluindo a function deleta(filme) conforme mostra o código a seguir:
(function (app) {
var listaController = function ($scope, filmeService)
{
filmeService
.getFilmes()
.success(function (data) {
$scope.filmes = data;
});
$scope.deleta = function (filme) {
filmeService.deletar(filme)
.success(function () {
removerFilmePorId(filme.Id);
});
};
var removerFilmePorId = function (id) {
for (var i = 0; i < $scope.filmes.length; i++) {
if ($scope.filmes[i].Id == id) {
$scope.filmes.splice(i, 1);
break;
}
}
};
};
app.controller("listaController", listaController)
}(angular.module("filmoteca")));
Temos agora duas novas functions no controller listaController. A primeira é a function deleta anexado ao objeto $scope e, por isso mesmo, este método é chamado pela diretiva ng-click que usa o serviço filmeService para deletar o filme.
Quando a chamada é feita com sucesso, é feito uma chamada à function removerFilmePorId(), que não está associada ao objeto $scope e, por isso, é uma implementação privada dentro do controlador. Esta function localiza e deleta o filme pelo seu id no modelo e o remove do array dos filmes.
Abaixo vemos a aparência da view lista.html:
Editando e criando filmes
Vamos agora implementar a edição e a criação de um novo filme. Podemos fazer isso de diversas formas e neste exemplo vamos adotar a seguinte abordagem:
- No arquivo lista.html, que exibe a lista de filmes e o botões – Detalhes e Deletar – vamos incluir um novo botão – Novo Filme – e vincular a esse botão uma diretiva ng-click que chama uma function criar();
- Vamos criar, então, um novo arquivo HTML, chamado edita.html, que vai funcionar como um formulário para criar um novo filme e para editar um filme existente. Este arquivo funciona como uma partial view e deverá ser incluído na view lista.html e também na viewdetalhes.html usando a diretiva ng-include.
Dessa forma, a view edita.html vai compartilhar a funcionalidade de incluir um filme e editar um filme.
Clique com o botão direito do mouse na pasta Html e, a seguir, em Add -> New Item e selecione o template HTML page e informe o nomeedita.html. A seguir, inclua o código abaixo nesta view:
<div ng-controller="editaController">
<form ng-show="isEditavel()">
<fieldset>
<div class="form-group">
<label for="titulo">
Titulo
</label>
<input id="titulo" type="text" ng-model="editar.filme.Titulo" required class="form-control" />
</div>
<div class="form-group">
<label for="anoLancamento">
Ano de Lançamento
</label>
<input id="anoLancamento" type="number" ng-model="editar.filme.AnoLancamento" required min="1900" max="2050" class="form-control" />
</div>
<div class="form-group">
<label for="duracao">
Duração
</label>
<input id="duracao" type="number" ng-model="editar.filme.Duracao" required min="10" max="500" class="form-control" />
</div>
<button class="btn btn-primary" ng-click="salvar()">Salvar</button>
<button class="btn btn-danger" ng-click="cancelar()">Cancelar</button>
</fieldset>
</form>
</div>
É muito importante entender esta view :
- Nesta view, usamos a diretiva ng-controller=”editaController”, que indica que o controlador editaController é responsável pelas functions usadas nesta view. Como este controlador ainda não existe, vamos ter que criá-lo posteriormente;
- A diretiva ng-show é usada para ocultar ou mostrar uma seção do DOM baseado na expressão usada: ng-show=”isEditavel()” que deve retornar true ou false; Neste caso, o elemento form somente será exibido quando a function isEditavel() retornar true a partir do model; Estamos usando esta diretiva para ocultar o formulário, exibindo-o somente para criar ou editar um novo filme;
- A diretiva ng-model define o two-way-binding entre o model e os elementos do formulário (textarea, select, input, etc); No formulário, definimos as seguintes diretivas ng-model:
- ng-model=”editar.filme.Titulo”
- ng-model=”editar.filme.AnoLancamento”
- ng-model=”editar.filme.Duracao”
Fazendo assim, criamos essas propriedades no objeto $scope e permitimos que elas sejam acessadas pelo controlador editaController que iremos criar.
Perceba que o objetivo das diretivas é fazer a vinculação entre o model e a view. O model (ou controller) nunca manipula diretamente os elementos DOM; quem faz isso são as diretivas. Fazendo uma alteração no model ela se reflete na view.
Vamos, então, alterar a view lista.html incluindo o botão para criar um novo filme e usar a diretiva ng-include para incluir a view edita.html:
<div ng-controller="listaController">
<table class="table">
<tr>
<th>Título</th>
</tr>
<tr ng-repeat="filme in filmes">
<td>{{filme.Titulo}}</td>
<td>
<a class="btn btn-primary" href="#/detalhes/{{filme.Id}}">Detalhes</a>
<button class="btn btn-danger" ng-click="deleta(filme)">Deletar</button>
</td>
</tr>
</table>
<button class="btn btn-success" ng-click="criar()">Novo Filme</button>
<div ng-include="'/Cliente/Html/edita.html'"></div>
</div>
Agora a view lista.html pode invocar o método criar() que será definido no model.
A diretiva ng-include faz a inclusão da view edita.html nesta view, exibindo o formulário para o usuário digitar as informações do novo livro.
Observe que usamos aspas simples(”) no interior da diretiva para chamar a página edita.html, assim asseguramos que o caminho informado será reconhecido como um literal string.
A function criar() definida deverá ser criada no controlador listaController, que é responsável por esta view. Altere o arquivolistaController.js incluindo a function criar():
(function (app) {
var listaController = function ($scope, filmeService)
{
filmeService
.getFilmes()
.success(function (data) {
$scope.filmes = data;
});
$scope.criar = function () {
$scope.editar = {
filme: {
Titulo: "",
Duracao: 0,
AnoLancamento: new Date().getFullYear()
}
};
};
$scope.deleta = function (filme) {
filmeService.deletar(filme)
.success(function () {
removerFilmePorId(filme.Id);
});
};
var removerFilmePorId = function (id) {
for (var i = 0; i < $scope.filmes.length; i++) {
if ($scope.filmes[i].Id == id) {
$scope.filmes.splice(i, 1);
break;
}
}
};
};
app.controller("listaController", listaController)
}(angular.module("filmoteca")));
Da mesma forma, vamos alterar a view detalhes.html para incluir um botão de comando vinculado a diretiva ng-click para editar os dados e outro para retornar para a lista. Vamos usar também a diretiva ng-include para incluir a view edita.html na view detalhes para exibir o formulário para editar os dados. Abaixo temos o código da view detalhes.html alterado:
<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>
<a class="btn btn-primary" ng-click="editar()">Editar</>
<a class="btn btn-success" href="#/">Retorna</a>
<div ng-include="'/Cliente/Html/edita.html'"></div>
</div>
Para concluir esta parte do artigo, vamos definir a function editar() no controlador detalhesController, conforme mostra o código a seguir:
(function (app) {
var detalhesController = function ($scope, $routeParams, filmeService) {
var id = $routeParams.id;
filmeService
.getFilmePorId(id)
.success(function (data) {
$scope.filme = data;
});
$scope.editar = function () {
$scope.editar.filme = angular.copy($scope.filme);
};
};
app.controller("detalhesController", detalhesController);
}(angular.module("filmoteca")));
A função editar() apenas faz uma cópia do filme selecionado no escopo para a propriedade filme, atualizando a view e exibindo os dados do filme selecionado para edição.
Executando o projeto agora, teremos o seguinte resultado:
1. A página inicial exibindo a view lista.html:
2. A exibição da view detalhes.html quando o usuário clica no botão Detalhes:
3. A exibição do formulário representado pela view edita.html, exibindo os dados do filme selecionado quando o usuário clica no botão Editar:
4. A exibição do formulário representado pela view edita.html quando o usuário clica no botão Novo Filme:
Na próxima parte do artigo, vamos implementar as funcionalidades do controlador editaController e definir as functions para criar um novo filme e alterar dados do filme selecionado.













