Análisis y ejemplos sobre el framework Kendo MVVM. Qué es el patron MVVM. Además realizamos nuestro primer ejemplo basado en esta librería Javascript.
Para aquellos que no lo conocen, Kendo es un framework Javascript que cuenta con soporte para las distintas plataformas de desarrollo (JAVA, PHP, ASP.NET y ASP.NET MVC) y que nos aporta una más que interesante colección de controles, simplificándonos el desarrollo de nuestra interfaz de usuario, y algo que está bastante de moda ahora es la utilización del patrón MVVM.
¿Qué es el patrón MVVM (Model-View-ViewModel)?
Es un patrón de diseño que fue definido por John Grossman, uno de los arquitectos que crearon WPF y Silverlight, como una variante del patrón MVP y que se asemeja al patrón MVC.Podríamos decir que este patrón viene a aunar las ventajas provenientes del patrón MVC con el potente enlace a datos que presentan WPF o Silverlight.
Las piezas que entran en juego dentro de MVVM son:
- Model: Es el objeto que contiene los datos que queremos visualizar, podríamos decir que es una objeto del dominio, o un DTO con la información necesaria para presentar los datos.
- View: Es la vista donde se van a representar los datos de nuestro modelo, y donde estarán además los controles que faciliten la interacción entre el usuario y la persistencia del objeto.
- View-Model: Esta “capa” es un objeto intermedio que realiza la función de enlazar los datos entre la vista y nuestro modelo. A través de la definición de propiedades en nuestro ViewModel podemos enlazarlas dentro de nuestra Vista para que se modifique la información, o para que se guarden los datos en una Base de Datos a través de pulsar un botón por ejemplo.
Kendo MVVM
Existen diferentes frameworks de Javascript que permiten utilizar el patrón MVVM de forma sencilla en entornos web, como pueden ser knockoutjs o angularjs, pero en este artículo vamos a ver cómo realizar la implementación de MVVM con Kendo.Para empezar a utilizar Kendo es necesario que lo descarguemos desde su web oficial www.telerik.com/download, donde encontraremos varias versiones de pago (con prueba de 30 días) y una versión de código abierto más reducida y sin tiques de soporte. Para este artículo voy a utilizar la versión OpenSource del mismo que ocupa aproximadamente 19 Mb.
Una vez descargado Kendo, vamos a empezar a escribir nuestro primer ejemplo con el editor que más nos guste.
Dentro de nuestro fichero HTML vamos a agregar las referencias Javascript a jQuery y al fichero kendo.web.min.js que hemos descargado.
Bien, una vez añadidas las referencias vamos a definir un viewModel sencillo:
var viewModel = kendo.observable({
Name: 'Javier Torrecilla',
Age: 30,
Description: 'Software Developer'
});
A continuación definiremos la vista que vamos a utilizar y veremos cómo gracias al atributo "data-bind" enlazaremos a nuestro viewModel.
<div id="example">
Name: <label data-bind='text: Name'></label> <br />
Age: <label data-bind='text: Age' ></label> <br />
Description: <label data-bind='text: Description' ></label><br />
</div>
El valor establecido dentro del atributo indica la propiedad del elemento HTML que vamos a utilizar, en este ejemplo la propiedad "text", y el elemento de nuestro "viewmodel" con el que se va a enlazar.
Por último será necesario que a través de Javascript indiquemos el enlace entre el viewModel y la vista, para ello utilizaremos el método "bind":
kendo.bind($("#example"), viewModel);
El primer parámetro es el contenedor que vamos a enlazar, en este caso es un "div" llamado "example", y el segundo parámetro es nuestro viewmodel.
Si visualizamos nuestra página web de ejemplo en cualquier navegador podremos ver algo similar a esta imagen:
A continuación vamos a definir una función en nuestro viewModel y un botón en la vista para invocar dicha acción:
var viewModel = kendo.observable({
Name: 'Javier Torrecilla',
Age: 30,
Description: 'Software Developer',
Greeting: function () {
alert('Good Morning');
}
});
La vista con el botón que lanza la funcionalidad nos quedaría así:
<div id="example">
Name: <label data-bind='text: Name'></label> <br />
Age: <label data-bind='text: Age' ></label> <br />
Description: <label data-bind='text: Description' ></label><br />
<input type='button' data-bind="click:Greeting" value="Say Hello"/>
</div>
Si refrescamos nuestro navegador, veremos el nuevo botón en la página, y si presionamos dicho botón se ejecutará el código de la función que hemos definido en la función "Greeting".
Como podéis observar en el tag data-bind, hemos indicado que el elemento que se va a enlazar es el evento clic del botón.
Características de Kendo MVVM
Ahora nos vamos a centrar en las características de este interesante framework para desarrollo de aplicaciones web con MVVM.
Ahora que ya tenemos una idea del patrón "Model-View-ViewModel" y vimos un ejemplo de su utilización en un entorno web gracias al framework Javascript Kendo, vamos a explicar algunas de las características relativas a este framework.
ObservableObject
Este objeto es la base del patrón MVVM, ya que es el "viewmodel" que vamos a utilizar para enlazar con nuestras vistas y nos permite llevar cabo el control de cambio en las propiedades de nuestro objeto. Para definir nuestro "viewmodel" lo podemos realizar de las dos siguientes maneras:
New kendo.data.ObservableObject:
var viewModel = new kendo.data.ObservableObject({
Name: 'Javier Torrecilla',
Age: 30,
Description: 'Software Developer',
Greeting: function () {
alert('Good Morning');
}
});
Kendo.observable:
var viewModel = kendo.observable({
Name: 'Javier Torrecilla',
Age: 30,
Description: 'Software Developer',
Greeting: function () {
alert('Good Morning');
}
});
Este segundo método realizará internamente una instancia de "kendo.data.ObservableObject", por lo que son dos definiciones iguales.
Para modificar las propiedades, o simplemente para poder acceder a ellas, es necesario realizarlo a través de los métodos "set" o "get" que vienen dados gracias al objeto "ObservableObject". Vamos a ver unos ejemplos:
Establecer una propiedad:
viewModel.set(‘Name’,’Alvaro Torrecilla’);
Acceder al valor de la propiedad:
viewModel.get(‘Name’);
Del mismo modo que se realiza con propiedades simples, lo podríamos realizar con otros objetos que sean propiedades de nuestro viewmodel, es decir, si tenemos otras clases complejas dentro:
Establecer una propiedad:
viewModel.set(‘Coche.Marca’,’Seat’);
Acceder al valor de la propiedad:
viewModel.get(‘Coche.Marca’);
ObservableArray
Este objeto nos permite tener un array de Javascript, pero con las ventajas del control de cambio en las propiedades del mismo modo que se tiene en "ObservableObject". Tal y como indicábamos con ObservableObject, también tenemos dos formas de llevar a cabo la definición de "ObservableArray" en nuestro código:
New kendo.data.ObservableObject:
var listModel = new kendo.data.ObservableArray([{
Name: 'Javier Torrecilla',
Age: 30,
Description: 'Software Developer',
Greeting: function () {
alert('Good Morning');
}
},{
Name: Alvaro Torrecilla',
Age: 3,
Description: ‘Student’,
Greeting: function () {
alert('Good Morning');
}
}
]);
Kendo.observable:
var listModel = kendo.observable(([{
Name: 'Javier Torrecilla',
Age: 30,
Description: 'Software Developer',
Greeting: function () {
alert('Good Morning');
}
},{
Name: Alvaro Torrecilla',
Age: 3,
Description: ‘Student’,
Greeting: function () {
alert('Good Morning');
}
}
]);
El segundo método se encargará de realizar una instancia de "ObservableArray", generando objetos completamente iguales ambas definiciones.
Binding
El binding es el enlace que vamos a realizar entre elementos HTML y las propiedades de nuestro "viewmodel". Para realizar el enlace vamos a utilizar el atributo “data-bind”, donde almacenaremos en una cadena de texto la propiedad que queremos enlazar y su valor de la siguiente manera:
<label data-bind='text: Name'></label>
En este ejemplo, estamos enlazando la propiedad "Text" del objeto "Label" a la propiedad "Name" de nuestro "viewmodel".
Dentro de la propiedad "data-bind" podremos indicar tantos “bindings” como deseemos separándolos por “,” e indicando las distintas propiedades y valores a los que queramos hacer referencia:
<label data-bind='text: Name,visible:IsNameVisible'></label>
Los atributos “preestablecidos” que nos permiten definir un binding son los siguientes: “Attr”, Checked, Click, Disabled, Enabled, Style, Text, Value, Visible, Html, Source o Events. Vamos a ver alguno de ellos más en detalle:
Attr
El binding a través de la propiedad "Attr" nos va a permitir el enlace a propiedades de cualquier propiedad del elemento indicado, y además nos va a permitir establecer el valor de elementos propios de HTML5 (data-xxx):
<img id="logo" data-bind="attr: { src: ImageUrl, alt: ImageAlt }" />
<div data-bind="attr: { data-content: Content }"></div>
Events
Una característica interesante que se puede definir con el binding es el enlace a eventos de un elemento del DOM, donde el método enlazado se llevará a cabo en el momento de producirse el evento indicado.
<input type=”text” data-bind=’value:Name,events:{click:Greeting}’/>
Source
Otra característica muy interesante viene dada gracias a propiedades de tipo "Array", es decir, cuando vamos a enlazar a un número "n" de elementos del mismo tipo.
Para aprovechar esta característica es necesario que hagamos uso de la definición de plantillas para indicar cómo será la visualización de los datos:
<script id="UserTemplate" type="text/x-kendo-template">
<li>
<img id="logo" data-bind="attr: { src: ImageUrl, alt: ImageAlt }" />
<span data-bind="text: Name"></span>
</li>
</script>
Después será necesario definir el atributo "data-template" y asignarle la plantilla que hemos definido
<ul data-template="UserTemplate" data-bind="source: Users">
</ul>
Si necesitamos realizar un enlace y no podemos hacer uso de los que hemos indicado anteriormente, KENDO nos brinda la posibilidad de definir nuestros Bindings personalizados.
Custom Binding
Para definir nuestro propio binding personalizado, es necesario extender el objeto "kendo.data.Binder". Podremos llevar a cabo de binding de 1 dirección (refrescar la vista) o bidireccional (refrescar vista y modelo). Para poder utilizar nuestros binding personalizados es muy importante definirlos antes de utilizarlos.
1 Dirección:
Vamos a definir un binding llamado fade para propiedades de tipo “Bool” cuando la propiedad sea “True” hará un fadeIn, en caso contrario hará un fadeOut. Con este binding, solo vamos a refrescar la vista por lo tanto el valor del viewmodel no se verá afectado.
kendo.data.binders.fade = kendo.data.Binder.extend({
refresh: function() {
var value = this.bindings["fade"].get();
if (value) {
$(this.element).fadeIn();
} else {
$(this.element).fadeOut();
}
}
});
2 Direcciones:
Vamos a definir otro binding de tipo “bool”, en este caso vamos a permitir que se modifique tanto la vista (al cambiar el viewModel) como el viewmodel (al cambiar la vista).
kendo.data.binders.bool = kendo.data.Binder.extend({
init: function(element, bindings, options) {
//call the base constructor
kendo.data.Binder.fn.init.call(this, element, bindings, options);
var that = this;
//listen for the change event of the element
$(that.element).on("change", function() {
that.change(); //call the change function
});
},
refresh: function() {
var that = this,
value = that.bindings["bool"].get();
$(that.element).val(value);
},
change: function() {
var value = this.element.value;
this.bindings["bool"].set(value);
}
});
Conclusiones
Con este artículo hemos visto una pequeña introducción al uso del patrón MVVM dentro del desarrollo web con el framework Kendo de Telerik.
Del mismo modo, hemos visto algunas de las características más interesantes que provee este framework, como los binding, los binding personalizados o el uso de templates.
Espero que os sea de utilidad.
Javier Torrecilla Puertas
Desarrollador en tecnologías .NET, colaborador en foros de MSDN, Geek.ms