lunes, 6 de agosto de 2012

Introducción a Knockout (VIII) - obsersable computed y binding event

Con los binding que trae knockout de fábrica debería ser más que suficiente para la mayoría de los proyectos en los que usemos knockout. Pese a ésto knockout nos brinda la forma de poder extender estos comportamientos predefinidos para poder tener un control total sobre nuestra vista y así no tener prácticamente ninguna limitación.

Computed Observables
Dentro de los observables que nos da knockout tenemos los computed observables (prefiero no traducirlo). Son funciones, que depende de uno o más observables y que se actualizan automáticamente cuando una de sus dependencias cambia. Típicamente se usan para información que se muestra en solo lectura aunque como veremos más adelante también los computed observables pueden ser de escritura y ellos a su vez puede actualizar valores.

Supongamos esta vista
<p>Nombre: <input type="text" data-bind="value: firstname" /></p>
<p>Apellidos: <input type="text" data-bind="value: lastname" /></p>
<p>Nombre completo: <label data-bind="text: name"></p>
Y este modelo
function ViewModel(model) {  
    var self = this;  
  
    self.firstname = ko.observable('');  
    self.lastname = ko.observable('');  
    self.name = ko.computed(function() {
        if (self.firstname() == '' || self.lastname() == '') return '';
         return self.lastname() + ', ' + self.firstname();
    });
}  

var viewModel = new ViewModel();  
ko.applyBindings(viewModel);​
Como vemos establecemos dos observables sobre firstname y lastname. También definimos observable computed que actualiza la propiedad name. Esta función se lanzará cada vez que la propiedades lastname y firstname cambien. Lo realmente maravilloso es que la función detecta a que propiedades debe detectar los cambios sin que nosotros debamos hacer nada más que usarlas en el cuerpo de la función.

Podemos probar este ejemplo en el siguiente enlace.

Como comentamos antes, los computed observables también pueden ser de escritura y ellos actualizar determinados valores. He de reconocer que esto no suele ser muy común pero puede que en algún momento nos sea útil. Para hacer un computed observables de lectura y escritura en el ejemplo anterior cambiaremos la vista
<p>Nombre: <input type="text" data-bind="value: firstname" /></p>
<p>Apellidos: <input type="text" data-bind="value: lastname" /></p>
<p>Nombre completo: <input type="text" data-bind="value: name"></p>
y el modelo de la siguiente manera
function ViewModel(model) {  
    var self = this;  
  
    self.firstname = ko.observable('');  
    self.lastname = ko.observable('');  
    self.name = ko.computed({
        read: function() {
            if (self.firstname() == '' || self.lastname() == '') return '';
                return self.lastname() + ', ' + self.firstname();
        },
        write: function(value) {
            var index = value.lastIndexOf(", ");
            if (index > 0) 
            { 
                self.firstname(value.substring(index + 2));
                self.lastname(value.substring(0, index));
            }
        }
    });
}  

var viewModel = new ViewModel();  
ko.applyBindings(viewModel);​
Tal y como hicimos antes, si actualizamos el nombre y los apellidos automáticamente se actualizará el campo del nombre del completo. La salvedad en este caso, es que si actualizamos el nombre completo nosotros con el formato apellidos, nombre, se actualizarán los campos nombre y apellidos.

Podemos probar este ejemplo en el siguiente enlace.

Binding Event
Otra de las posibilidades que nos da knockout es trabajar directamente con los eventos que tienes javascript, pese a que ya tenemos algunos bindings que trabajan con ellos como puede ser el binding click.
Por ejemplo, si definimos la siguiente vista
<div>
    <input type="text" data-bind="value: message, event: { keyup: onkeyup }" />
    <label data-bind="text: status" ></label>
</div>​
y el siguiente modelo
function ViewModel(model) {  
    var self = this; 

    self.message = ko.observable('');
    self.status = ko.observable('Has escrito 0 caracteres...');
  
    self.onkeyup = function(data, event) {
        self.status('Has escrito ' + event.target.value.length + ' caracteres...');           
        return true;
    }
}  
ko.applyBindings(new ViewModel());
En este ejemplo estamos enganchándonos al evento keyup de un textbox y actualizamos un label con la información del número de caracteres que hemos introducido en el textbox.

Podemos probar este ejemplo en el siguiente enlace.

Como vemos, knoutout es bastante versátil y prácticamente podemos hacer lo que queramos. En el próximo artículo veremos como hacer nuestros propios bindings que también nos pueden ser útiles en algunos contextos.

Happy coding!

No hay comentarios:

Publicar un comentario