Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
de Rick Anderson
Descargar el proyecto completado
Creación de una interfaz de usuario dinámica con Knockout.js
En esta sección, usaremos Knockout.js para agregar funcionalidad a la vista Administrador.
Knockout.js es una biblioteca de Javascript que facilita el enlace de controles HTML a datos. Knockout.js usa el patrón Model-View-ViewModel (MVVM).
- El modelo es la representación del lado servidor de los datos en el dominio empresarial (en nuestro caso, productos y pedidos).
- La vista es la capa de presentación (HTML).
- El modelo de vista es un objeto javascript que contiene los datos del modelo. El modelo de vista es una abstracción de código de la interfaz de usuario. No tiene conocimiento de la representación HTML. En su lugar, representa características abstractas de la vista, como "una lista de elementos".
La vista está enlazada al modelo de vista mediante datos. Las actualizaciones del modelo de vista se reflejan automáticamente en la vista. El modelo de la vista también obtiene eventos de la vista, como clics de botón, y realiza operaciones en el modelo, como creación de un pedido.
Diagrama que muestra la interacción entre los datos de H T M L, el modelo de vista, j son y el controlador web A P I. El cuadro de datos H T M L está etiquetado como vista. Una flecha doble etiquetada como enlace de datos vincula el cuadro de datos HTML al cuadro de modelo de vista. Una flecha doble con la etiqueta H T T P requests y modelo JSON desde el servidor vincula el modelo de vista al controlador de API web.
En primer lugar, definiremos el modelo de vista. Después, enlazaremos el marcado HTML al modelo de vista.
Agregue la siguiente sección de Razor a 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>
}
Puede agregar esta sección en cualquier lugar del archivo. Cuando se renderiza la vista, la sección aparece en la parte inferior de la página HTML, justo antes de la etiqueta de cierre </body>.
Todo el script de esta página irá dentro de la etiqueta de script indicada por el comentario:
<script type="text/javascript">
// View-model will go here
</script>
En primer lugar, defina una clase de modelo de vista:
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
}
ko.observableArray es un tipo especial de objeto en Knockout, denominado observable. En la documentación de Knockout.js: un observable es un "objeto de JavaScript que puede notificar a los suscriptores sobre los cambios". Cuando el contenido de un observable cambia, la vista se actualiza automáticamente para reflejar los cambios.
Para rellenar la products matriz, realice una solicitud AJAX a la API web. Recuerde que almacenamos el URI base para la API en el contenedor de vistas (consulte la parte 4 del tutorial).
function ProductsViewModel() {
var self = this;
self.products = ko.observableArray();
// New code
var baseUri = '@ViewBag.ApiUrl';
$.getJSON(baseUri, self.products);
}
A continuación, agregue funciones al modelo de vista para crear, actualizar y eliminar productos. Estas funciones envían llamadas AJAX a la API web y usan los resultados para actualizar el modelo de vista.
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);
}
Ahora la parte más importante: cuando el DOM está completamente cargado, llame a la función ko.applyBindings y pase una nueva instancia de ProductsViewModel.
$(document).ready(function () {
ko.applyBindings(new ProductsViewModel());
})
El método ko.applyBindings activa Knockout y conecta el modelo de vista a la vista.
Ahora que tenemos un modelo de vista, podemos crear las vinculaciones. En Knockout.js, puede hacerlo agregando data-bind atributos a elementos HTML. Por ejemplo, para enlazar una lista HTML a una matriz, use el foreach enlace:
<ul id="update-products" data-bind="foreach: products">
El foreach enlace recorre en iteración la matriz y crea elementos secundarios para cada objeto de la matriz. Los enlaces de los elementos secundarios pueden hacer referencia a las propiedades de los objetos de matriz.
Agregue los siguientes enlaces a la lista "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>
El <li> elemento se produce dentro del ámbito del enlace foreach . Esto significa que Knockout representará el elemento una vez para cada producto de la products matriz. Todos los enlaces del <li> elemento hacen referencia a esa instancia de producto. Por ejemplo, $data.Name hace referencia a la Name propiedad del producto.
Para establecer los valores de las entradas de texto, use la vinculación value. Los botones están vinculados a funciones en el modelo-vista mediante la vinculación click. La instancia del producto se pasa como parámetro a cada función. Para obtener más información, la documentación de Knockout.js tiene buenas descripciones de las distintas vinculaciones.
A continuación, agregue una vinculación para el evento submit en el formulario Agregar Producto.
<form id="addProduct" data-bind="submit: create">
Este enlace llama a la create función en el modelo de vista para crear un nuevo producto.
Este es el código completo de la vista 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>
Ejecute la aplicación, inicie sesión con la cuenta de administrador y haga clic en el vínculo "Admin". Debería ver la lista de productos y poder crear, actualizar o eliminar productos.