Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
por Rick Anderson
Criar uma interface dinâmica com Knockout.js
Nesta secção, vamos usar Knockout.js para adicionar funcionalidade à vista de Administrador.
Knockout.js é uma biblioteca Javascript que facilita a atribuição de controlos HTML a dados. Knockout.js utiliza o padrão Model-View-ViewModel (MVVM).
- O modelo é a representação do lado do servidor dos dados no domínio empresarial (no nosso caso, produtos e encomendas).
- A vista é a camada de apresentação (HTML).
- O view-model é um objeto Javascript que contém os dados do modelo. O modelo de visualização é uma abstração de código da interface. Não tem conhecimento da representação HTML. Em vez disso, representa características abstratas da vista, como "uma lista de itens".
A visualização está vinculada ao modelo de visualização. As atualizações ao modelo de visualização são automaticamente refletidas na visualização. O modelo de visualização também recebe eventos da vista, como cliques de botões, e realiza operações no modelo, como criar um pedido.
Diagrama que mostra a interação entre os dados H T M L, o modelo de visualização, j son e o controlador Web A P I. A caixa de dados H T M L está rotulada como vista. Uma seta dupla rotulada como data binding liga a caixa de dados H T M L à caixa do modelo de visualização. Uma seta dupla rotulada com pedidos HTTP e modelo JSON do servidor liga o modelo de vista ao controlador API Web.
Primeiro, vamos definir o modelo de visualização. Depois disso, vamos associar a marcação HTML ao modelo de visualização.
Adicione a seguinte secção Razor ao Admin.cshtml:
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.1.0.js")"></script>
<script type="text/javascript">
// View-model will go here
</script>
}
Pode adicionar esta secção em qualquer parte do ficheiro. Quando a visualização é renderizada, a secção aparece no final da página HTML, mesmo antes da etiqueta de encerramento </body> .
Todo o script desta página irá dentro da tag script indicada pelo comentário:
<script type="text/javascript">
// View-model will go here
</script>
Primeiro, defina uma classe view-model:
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
}
ko.observableArray é um tipo especial de objeto em Knockout, chamado observável. Segundo a documentação Knockout.js: Um observável é um "objeto JavaScript que pode notificar assinantes sobre alterações." Quando o conteúdo de um observável muda, a interface é automaticamente atualizada em conformidade.
Para preencher o products array, faça um pedido AJAX à API web. Lembre-se que armazenámos o URI base da API no "view bag" (ver Parte 4 do tutorial).
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
// New code
var baseUri = '@ViewBag.ApiUrl';
$.getJSON(baseUri, self.products);
}
De seguida, adicione funções ao modelo de visualização para criar, atualizar e eliminar produtos. Estas funções submetem chamadas AJAX para a API web e usam os resultados para atualizar o modelo de visualização.
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
var baseUri = '@ViewBag.ApiUrl';
// New code
self.create = function (formElement) {
// If the form data is valid, post the serialized form data to the web API.
$(formElement).validate();
if ($(formElement).valid()) {
$.post(baseUri, $(formElement).serialize(), null, "json")
.done(function (o) {
// Add the new product to the view-model.
self.products.push(o);
});
}
}
self.update = function (product) {
$.ajax({ type: "PUT", url: baseUri + '/' + product.Id, data: product });
}
self.remove = function (product) {
// First remove from the server, then from the view-model.
$.ajax({ type: "DELETE", url: baseUri + '/' + product.Id })
.done(function () { self.products.remove(product); });
}
$.getJSON(baseUri, self.products);
}
Agora a parte mais importante: Quando o DOM estiver totalmente carregado, chame a função ko.applyBindings e passe uma nova instância do ProductsViewModel:
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
O método ko.applyBindings ativa o Knockout e liga o modelo de visualização à vista.
Agora que temos um modelo de visualização, podemos criar as ligações. Em Knockout.js, faz-se isto adicionando data-bind atributos a elementos HTML. Por exemplo, para associar uma lista HTML a um array, use a foreach vinculação.
<ul id="update-products" data-bind="foreach: products">
A foreach ligação itera através do array e cria elementos filhos para cada objeto do array. As ligações nos elementos filhos podem referenciar propriedades nos objetos da matriz.
Adicione as seguintes associações à lista de "update-products":
<ul id="update-products" data-bind="foreach: products">
<li>
<div>
<div class="item">Product ID</div> <span data-bind="text: $data.Id"></span>
</div>
<div>
<div class="item">Name</div>
<input type="text" data-bind="value: $data.Name"/>
</div>
<div>
<div class="item">Price ($)</div>
<input type="text" data-bind="value: $data.Price"/>
</div>
<div>
<div class="item">Actual Cost ($)</div>
<input type="text" data-bind="value: $data.ActualCost"/>
</div>
<div>
<input type="button" value="Update" data-bind="click: $root.update"/>
<input type="button" value="Delete Item" data-bind="click: $root.remove"/>
</div>
</li>
</ul>
O <li> elemento ocorre dentro do âmbito da ligação foreach . Isto significa que o Knockout irá renderizar o elemento uma vez para cada produto no products array. Todas as ligações dentro do <li> elemento referem-se àquela instância do produto. Por exemplo, $data.Name refere-se à propriedade Name do produto.
Para definir os valores das entradas de texto, use o value binding. Os botões estão associados a funções no modelo-vista, usando a vinculação click. A instância do produto é passada como parâmetro a cada função. Para mais informações, a documentação Knockout.js tem boas descrições das várias ligações.
De seguida, adicione uma ligação para o evento de submissão no formulário Adicionar Produto:
<form id="addProduct" data-bind="submit: create">
Esta ligação chama a função create no view model para criar um novo produto.
Aqui está o código completo para a vista de Administrador:
@model ProductStore.Models.Product
@{
ViewBag.Title = "Admin";
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.0.0.js")"></script>
<script type="text/javascript">
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
var baseUri = '@ViewBag.ApiUrl';
self.create = function (formElement) {
// If valid, post the serialized form data to the web api
$(formElement).validate();
if ($(formElement).valid()) {
$.post(baseUri, $(formElement).serialize(), null, "json")
.done(function (o) { self.products.push(o); });
}
}
self.update = function (product) {
$.ajax({ type: "PUT", url: baseUri + '/' + product.Id, data: product });
}
self.remove = function (product) {
// First remove from the server, then from the UI
$.ajax({ type: "DELETE", url: baseUri + '/' + product.Id })
.done(function () { self.products.remove(product); });
}
$.getJSON(baseUri, self.products);
}
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
</script>
}
<h2>Admin</h2>
<div class="content">
<div class="float-left">
<ul id="update-products" data-bind="foreach: products">
<li>
<div>
<div class="item">Product ID</div> <span data-bind="text: $data.Id"></span>
</div>
<div>
<div class="item">Name</div>
<input type="text" data-bind="value: $data.Name"/>
</div>
<div>
<div class="item">Price ($)</div>
<input type="text" data-bind="value: $data.Price"/>
</div>
<div>
<div class="item">Actual Cost ($)</div>
<input type="text" data-bind="value: $data.ActualCost"/>
</div>
<div>
<input type="button" value="Update" data-bind="click: $root.update"/>
<input type="button" value="Delete Item" data-bind="click: $root.remove"/>
</div>
</li>
</ul>
</div>
<div class="float-right">
<h2>Add New Product</h2>
<form id="addProduct" data-bind="submit: create">
@Html.ValidationSummary(true)
<fieldset>
<legend>Contact</legend>
@Html.EditorForModel()
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
</div>
</div>
Executa a aplicação, inicia sessão com a conta de Administrador e clica no link "Administrador". Deverias ver a lista de produtos e conseguir criar, atualizar ou eliminar produtos.