ASP .NET - KnockoutJS conceitos básicos
A KnockoutJS é uma library JavaScript Open Source que usa o padrão MVVM (Model-View-ViewModel) para criar interfaces de usuário através de ligações declarativas de dados, interface de atualização automática, rastreamento de dependência e modelagem do lado cliente. O conceito de MVVM deve ser muito intuitivo e familiar, especialmente para pessoas com experiência em WPF. (Veja as referências para saber mais sobre o padrão MVVM)
Você pode obter mais informações e detalhes bem como baixar a library JavaScript no site oficial do KnockoutJS - http://knockoutjs.com/
Existe um tutorial on-line rápido que pode ser acessado neste link: http://learn.knockoutjs.com/
Neste artigo eu vou tratar de conceitos básicos para utilização de Knockout em páginas ASP .NET mostrando como persistir o view-model entre os postbacks.
Recursos usados:
Obs: Eu estou usando as versões para desenvolvimento que não estão compactadas. Para produção use as versões compactadas das library jQuery e Knockout.
Criando o projeto ASP .NET
Abra o Visual Studio Express 2012 for web e no menu FILE clique em New Project e selecione o template Visual C# -> Web e a seguir ASP .NET Web Application informando o nome Knockout_Basico;
A seguir vamos criar uma pasta no projeto chamada Scripts. Clique com o botão direito do mouse sobre o projeto e selecione Add -> New Folder e informe o nome Scripts.
Agora vamos incluir a biblioteca Knockout.js que você já baixou do site oficial na pasta Scripts. Clique com o botão direito sobre a pasta e selecione Add-> Existing Item e selecione o arquivo knockout-2.2.1.js do na sua máquina local.
Vamos agora incluir uma página no projeto. Clique no menu PROJECT e a seguir em Add New Item e selecione o template Web Form informando o nome Default.aspx e clicando em Add;
Neste momento o seu projeto deverá ter a seguinte estrutura:
Vamos abrir a página Default.aspx e no modo Source vamos incluir o código abaixo:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Knockout_Basico.Default" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Knockout Básico</title> <script type="text/javascript" src="Scripts/knockout-2.2.1.js"></script> </head> <body> <form id="form1" runat="server"> <div> <span class="auto-style4"><strong><span class="auto-style5">Macoratti.net - Knockout Básico</span> </strong></span> <hr> <table border="1"> <tbody><tr> <td class="auto-style3"> <span class="auto-style2">Alterar a visibilidade da próxima linha</span> <input type="checkbox" data-bind="checked: isRowVisible" class="auto-style2" /> <span class="auto-style2"> </span> </td> </tr> <tr data-bind="visible: isRowVisible"> <td class="auto-style2"> Esta é a linha cuja visibilidade pode ser alterada. </td> </tr> </tbody></table> </div> </form> </body> <script type="text/javascript"> var viewModel = { isRowVisible: ko.observable(false) }; ko.applyBindings(viewModel); </script> </html> |
Vejamos o código
destacado em azul:
|
Usando controles ASP .NET
No exemplo acima usamos um controle HTML ( <input type="checkbox" ) e se usarmos o controle ASP .NET checkbox conforme abaixo:
<asp:CheckBox ID="chkChangeVisibility" runat="server" data-bind="checked: isRowVisible" />
Se comentarmos a linha onde usamos o controle HTML e inserirmos a linha acima ao rodarmos o projeto vamos constatar que o código não funciona. Para que ele funcione temos que definir no code-behind do arquivo Default.aspx.cs o código abaixo no evento Load:
using System; namespace Knockout_Basico { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { chkChangeVisibility.InputAttributes["data-bind"] = "checked: isRowVisible"; } } } |
Persistindo o View Model entre os postbacks
É usual para uma página ASP.NET fazer postagens para o servidor. Se fizermos uma postagem na página do , nosso exemplo, vai parecer que após a postagem, todas as nossas alterações são perdidas. Este é um problema comum com alterações JavaScript. Nosso Model View será carregado novamente do zero e o estado inicial será estabelecido novamente. É o comportamento normal para o modelo ASP .NET.
Para salvar as mudanças feitas vamos usar a mesma lógica que de como ViewState é mantido na ASP.NET. Vamos guardar o nosso Model View em um campo oculto.
Então temos que adicionar um campo oculto para a nossa página definindo o código: <input type="hidden" runat="server" id="hViewStateStorage" />
Vamos definir o código acima logo abaixo da declaração : <form id="form1" runat="server">
Agora devemos escrever nossa Model View para este campo. Na maioria dos casos, o estado inicial do controle é definido no lado do servidor. Nós vamos usar esta técnica também. No lado do servidor, vamos criar um objeto do Model View, serializá-lo no formato JSON e colocar a string JSON no campo oculto.
Alterando o código do evento Load teremos:
using System; using System.Web.Script.Serialization; namespace Knockout_Basico { public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { chkChangeVisibility.InputAttributes["data-bind"] = "checked: isRowVisible"; if (!IsPostBack) { var viewModel = new { isRowVisible = true }; var serializer = new JavaScriptSerializer { MaxJsonLength = int.MaxValue }; var json = serializer.Serialize(viewModel); hViewStateStorage.Value = json; } } } } |
Como você pode ver, usamos uma classe anônima e isso significa que você não precisa criar uma classe separada para o modelo de exibição no lado do servidor.
Outra possibilidade aqui é mudar o View Model durante o postback. Como ele é armazenado em um campo oculto, você pode extrair o Model-View a partir daí, desserializá-lo, analisar e alterar suas propriedades, serializá-lo e colocá-lo no campo oculto novamente. Neste caso, você precisa criar uma classe separada para o View Model para desserializar o modelo.
Agora temos que extrair o View Model do campo oculto no código JavaScript. Aqui está como fazer isso:
var stringViewModel
= document.getElementById('<%=hViewStateStorage.ClientID
%>').value; var viewModel = ko.utils.parseJson(stringViewModel); |
Aqui usamos a função parseJson da biblioteca KnockoutJS para converter a representação de string em um objeto JavaScript.
Mas agora estamos diante de um pequeno problema. Como eu disse, todas as propriedades do Model-View devem ser inicializadas usando a função ko.observable, o que não ocorre aqui. O seguinte código resolve o problema:
for (var
propertyName in viewModel) { viewModel[propertyName] = ko.observable(viewModel[propertyName]); } |
Agora, o Model View vem do servidor perfeitamente. A única coisa a fazer é guardá-lo para o campo oculto antes de postagem. Eu usei jQuery para assinar o evento de postagem:
$(document.forms[0]).submit(function
() { for (var propertyName in viewModel) { viewModel[propertyName] = ko.utils.unwrapObservable(viewModel[propertyName]); } document.getElementById('<%=hViewStateStorage.ClientID %>').value = ko.utils.stringifyJson(viewModel); |
E com isso conseguirmos o nosso intento persistir o View Model entre o postbacks.
Veja o código completo do arquivo Default.aspx abaixo:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Knockout_Basico.Default" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Knockout Básico</title> <script type="text/javascript" src="Scripts/knockout-2.2.1.js"></script> </head> <body> <form id="form1" runat="server"> <input type="hidden" runat="server" id="hViewStateStorage" /> <div> <span class="auto-style4"><strong><span class="auto-style5">Macoratti.net - Knockout Básico</span></strong></span> <hr> <table border="1"> <tbody><tr> <td class="auto-style3"> <span class="auto-style2">Alterar a visibilidade da próxima linha</span> <!--<input type="checkbox" data-bind="checked: isRowVisible" class="auto-style2" />--> <asp:CheckBox ID="chkChangeVisibility" runat="server" data-bind="checked: isRowVisible" /> <span class="auto-style2"> </span> </td> </tr> <tr data-bind="visible: isRowVisible"> <td class="auto-style2"> Esta é a linha cuja visibilidade pode ser alterada. </td> </tr> </tbody></table> <input id="Submit1" runat="server" type="submit" /> </div> </form> </body> <script type="text/javascript"> var stringViewModel = document.getElementById('<%=hViewStateStorage.ClientID %>').value; var viewModel = ko.utils.parseJson(stringViewModel); for (var propertyName in viewModel) { viewModel[propertyName] = ko.observable(viewModel[propertyName]); } ko.applyBindings(viewModel); $(document.forms[0]).submit(function () { for (var propertyName in viewModel) { viewModel[propertyName] = ko.utils.unwrapObservable(viewModel[propertyName]); } document.getElementById('<%=hViewStateStorage.ClientID %>').value = ko.utils.stringifyJson(viewModel); }); </script> </html> |
Joã 12:24
Em verdade, em verdade vos digo: Se o grão de trigo caindo na terra não morrer, fica ele só; mas se morrer, dá muito fruto.Joã 12:25
Quem ama a sua vida, perdê-la-á; e quem neste mundo odeia a a sua vida, guardá-la-á para a vida eterna.Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#