Eventos y Modelos en Backbone.js
Por Ismael Fernández | 157 vistas | Lectura de 8 minutos
1. Introducción
En el tutorial anterior, 'Introducción a Backbone.js', hicimos una breve presentación de este poderoso framework de JavaScript que nos permite crear aplicaciones SPA (Single Page Application), facilitando la implementación del patrón MVC (Modelo Vista Controlador) en todas ellas.
Ahora, en este tutorial, como mencioné anteriormente, daremos un paso más y nos adentraremos en cómo utilizar los eventos y modelos de Backbone.js en nuestra aplicación.
2. Eventos
Como les mencioné en 'Introducción a Backbone.js', la forma en que comunicamos las distintas partes de nuestra aplicación es mediante el lanzamiento de eventos entre ellas. Es decir, podemos hacer que una vista se suscriba a determinados eventos de un modelo para que, cuando éste cambie y lance dichos eventos, la vista renderice ese cambio de alguna manera.
En Backbone, los eventos son un módulo más dentro de la librería. Para dar a un objeto la habilidad de lanzar un evento que pueda ser escuchado por el resto de componentes en nuestra aplicación, debemos extender la funcionalidad de dicho objeto con la clase Backbone.Events:
var testObject = {};
_.extend(testObject, Backbone.Events);
Función 'trigger'
A partir de este momento, nuestro objeto podrá generar eventos dentro del contexto de nuestra aplicación que serán escuchados por todos los componentes que estén suscritos al mismo. Para lograrlo, usaremos la función "trigger". Esta función toma como parámetro el nombre del evento y los argumentos que queremos enviar al callback que se ejecutará cuando se genere el evento.
var params = 'estoy lanzando un evento'
testObject.trigger('test:fire:event', params);
Por convención, y con el propósito de distinguir los eventos de una aplicación, utilizaremos dos puntos (:) en los nombres de los eventos. Por ejemplo, en el nombre del evento anteriormente mencionado: "test:fire:event".
Función 'on'
Para que los demás componentes de la aplicación, que necesiten escuchar el evento lanzado, puedan reaccionar al evento, será necesario que se suscriban al mismo. Para lograrlo, utilizaremos la función "on". Esta función toma como parámetro el nombre del evento que se escuchará y la callback que se ejecutará cuando el evento sea lanzado:
var listener = {};
_.extend(listener, Backbone.Events);
listener.on('test:fire:event', function(data) {
console.log(data)
});
Función 'listenTo'
Lo que hace la función anterior es lanzar el evento a toda la aplicación, de manera que todos los componentes de la misma podrán escuchar dicho evento. Sin embargo, es posible que algún componente solo quiera escuchar un evento en particular. Para ese caso, utilizaremos la función "listenTo". Esta función permite escuchar eventos de un objeto específico. Toma como parámetro la instancia del objeto a escuchar, el nombre del evento y la callback que se ejecutará cuando el evento sea lanzado:
var listener = {};
_.extend(listener, Backbone.Events);
listener.listenTo(testObject, 'test:fire:event', function(data) {
console.log(data)
});
3. Modelos
En una aplicación JavaScript, los modelos son una parte fundamental. Son responsables de contener y manejar los datos de la aplicación, así como de gestionar la lógica de la misma.
Para crear un modelo, es necesario extender la clase Backbone.Model:
var Alumno = Backbone.Model.extend({});
Constructor
Una vez creado nuestro modelo "Alumno", podemos crear instancias del mismo utilizando la palabra reservada "new".
var alumno = new Alumno({});
De igual manera, es posible crear una instancia pasando como parámetro un objeto con los atributos y sus valores correspondientes que se desean asignar al modelo:
var alumno = new Alumno({
nombre: 'Ismael',
apellidos: 'Fernández Molina',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
});
defaults
Para crear un modelo con atributos por defecto, se utiliza el hash "defaults". Este hash creará de manera automática los atributos especificados con los valores correspondientes cada vez que se crea una instancia del modelo.
var Alumno = Backbone.Model.extend({
defaults: {
nombre: '',
apellidos: '',
dni: '',
edad: 0,
titulacion: ''
}
});
var alumno = new Alumno();
Función 'get'
Para obtener los valores de los atributos de una instancia de un modelo, se utiliza la función "get". Para obtener los valores, se pasa como parámetro una cadena con el nombre del atributo:
var alumno = new Alumno({
nombre: 'Ismael',
apellidos: 'Fernández Molina',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
});
console.log(alumno.get('nombre'));
console.log(alumno.get('apellidos'));
console.log(alumno.get('edad'));
console.log(alumno.get('titulacion'));
console.log(alumno.get('dni'));
Función 'set'
Para establecer valores a un atributo del modelo, se utiliza la función "set". Esta función toma como parámetros el nombre del atributo y el valor que se desea asignar:
alumno.set('nombre', 'Manuel');
alumno.set('apellidos', 'García Montes');
alumno.set('edad', '22');
Si es necesario cambiar varios valores a la vez, la función "set" también puede recibir un objeto con todos los valores que se desean cambiar:
alumno.set({
nombre: 'Manuel',
apellidos: 'García Montes',
edad: 22
});
Función 'unset'
Para eliminar atributos de un modelo, se utiliza la función "unset". Esta función toma como parámetro el nombre del atributo que se desea eliminar del modelo:
var alumno = new Alumno({
nombre: 'Ismael',
apellidos: 'Fernández Molina',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
});
alumno.unset('titulacion');
alumno.unset('edad');
Atributo 'cid'
El atributo "cid" es una cadena auto-generada por Backbone que identifica cada una de las instancias de los modelos creados en nuestra aplicación. No es recomendable utilizar este atributo como identificador del modelo. Por lo tanto, es necesario crear un identificador personalizado para gestionar nuestras entidades y evitar problemas con el "cid".
var alumno = new Alumno({
nombre: 'Ismael',
apellidos: 'Fernández Molina',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
}),
alumno2 = new Alumno({
nombre: 'Manuel',
apellidos: 'García Montes',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
});
console.log(alumno.cid);
console.log(alumno2.cid);
Atributo 'id'
Para definir el identificador del modelo, se establece el atributo "id", que se utilizará como identificador único del modelo y también para crear las URLs de persistencia con el servidor.
var alumno = new Alumno({
nombre: 'Ismael',
apellidos: 'Fernández Molina',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
});
alumno.set('id', '984651');
Atributo 'idAttribute'
Como acabamos de ver, en Backbone el atributo 'id' es usado como identificador del modelo, pero si la comunicación con el backend es directa y el identificador del modelo en el backend no se llama 'id', podemos indicar a Backbone que use otro atributo como identificador. Para hacerlo, utilizaremos el atributo 'idAttribute':
var Alumno = Backbone.Model.extend({
idAttribute: 'codAlumno',
defaults: {
nombre: '',
apellidos: '',
dni: '',
edad: 0,
titulacion: ''
}
});
4. Sincronización con el backend
Los modelos de Backbone están diseñados para soportar la persistencia de datos. Proporciona una serie de funciones que nos serán muy útiles para almacenar los datos, lo que nos ahorrará tiempo ya que no tendremos que desarrollar manualmente las llamadas a los backends.
Backbone.sync
Backbone nos provee de una función que nos permite interactuar con los backends para persistir o recuperar datos de modelos. Dicha función es Backbone.sync. Esta función recibe como parámetros el método que se va a ejecutar («create», «read», «update», «delete»), el modelo en cuestión y parámetros opcionales como los callbacks cuando la función ha funcionado correctamente o ha fallado.
El funcionamiento de Backbone.sync es el siguiente: cuando hacemos una llamada al backend con Backbone.sync, ésta toma todos los atributos del modelo, convierte los datos en un json y lanza una petición HTTP indicando que los datos que van a viajar son de tipo json (content-type: application/json). Dependiendo de la respuesta del backend (si devuelve datos o no), el modelo se actualizará con los datos que se devuelvan o no.
Como ya hemos mencionado anteriormente, Backbone buscará el identificador del modelo para construir las llamadas (REST) a los backends. De esta manera, tendremos lo siguiente:
- method:'read' –> verbo:GET –> url:'/modelName[/id]'
- method:'create' –> verbo:POST –> url:'/modelName'
- method:'update' –> verbo:PUT –> url:'/modelName/id'
- method:'patch' –> verbo:PATCH –> url:'/modelName/id'
- method:'delete' –> verbo:DELETE –> url:'/modelName/id'
Función 'fetch'
Esta función utiliza internamente Backbone.sync para obtener los datos del modelo desde el backend.
var alumno = new Alumno({
id: 1,
nombre: '',
apellidos: '',
dni: '',
edad: 0,
titulacion: ''
});
alumno.fetch();
Función 'save'
Esta función usa internamente Backbone.sync para guardar los datos del modelo en el backend (ya sea en el servidor, archivo, etc.). Puede recibir un objeto con los datos del modelo que se van a modificar como parámetro, aunque luego enviará internamente el objeto completo con los datos del modelo. Si el modelo ya existe, internamente se lanzará una actualización (method: update –> PUT), de lo contrario, si es nuevo, se lanzará una creación (method: create –> POST).
var alumno = new Alumno({
id: 1,
nombre: 'Ismael',
apellidos: 'Fernández Molina',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
});
alumno.save({
nombre: 'Manuel',
apellidos: 'García Montes'
});
Esta función, cada vez que es llamada, ejecuta el método 'validate' del modelo (si está definido) para verificar si los datos del modelo son correctos y si se puede continuar con el guardado de los datos. Si el método 'validate' indica lo contrario, la función 'save' se detendrá y devolverá un callback con el error correspondiente. El método 'validate' recibe un objeto con los atributos del modelo como parámetro.
var Alumno = Backbone.Model.extend({
defaults: {
nombre: '',
apellidos: '',
dni: '',
edad: 0,
titulacion: ''
},
validate: function(attributes) {
if (attributes.id <= 0) {
return 'El id del alumno no es válido';
}
}
});
Función 'destroy'
Esta función elimina un modelo del servidor. Al igual que las funciones anteriores, delega la responsabilidad a Backbone.sync, el cual lo traducirá a una petición HTTP de tipo DELETE.
var alumno = new Alumno({
id: 1
nombre: 'Ismael',
apellidos: 'Fernández Molina',
dni: '77777777S',
edad: 30,
titulacion: 'Ingeniería Informática'
});
alumno.destroy();
5. Eventos lanzados por defecto
En este tutorial hemos visto cómo podemos hacer que ciertas partes de nuestra aplicación escuchen eventos que los modelos de Backbone pueden lanzar. En los ejemplos que he mostrado, se programó manualmente el lanzamiento de eventos. Sin embargo, los modelos de Backbone lanzan eventos por defecto cada vez que ocurre algo con los datos que manejan.
Aquí les dejo la lista de eventos que se lanzan por defecto:
- add — cuando se agrega un modelo a una colección (hablaremos sobre colecciones en el siguiente tutorial)
- remove — cuando se elimina un modelo de una colección
- change — cada vez que se actualiza un atributo de un modelo
- change:[atributo] — cada vez que se actualiza un atributo específico del modelo ([atributo])
- destroy — cuando se elimina un modelo
- request — cuando un modelo inicia una petición hacia el backend
- sync — cuando la llamada que un modelo hace hacia el backend se ejecuta de forma satisfactoria
- error — cuando la llamada que un modelo hace hacia el backend falla
- invalid — cuando la validación de un modelo falla
- all — este evento se lanza cada vez que cualquier evento es lanzado en nuestra aplicación
Hasta este punto podemos decir que los modelos de Backbone contienen muchas más funciones relacionadas con el manejo de los datos. Aquí hemos detallado algunas de las principales que más se usan al desarrollar una aplicación. Si desean ampliar su conocimiento sobre las funciones que nos proporcionan los modelos de Backbone, pueden revisar la documentación oficial de Backbone.js.
6. Conclusiones
Como pueden ver, Backbone nos brinda muchas funciones para manejar los modelos en nuestra aplicación. Como hemos mencionado, los modelos son el corazón de nuestra aplicación y gracias a la gran cantidad de funciones y utilidades que ya proporciona este potente framework, podemos gestionar la lógica de la aplicación de manera sencilla. Solo es cuestión de practicar para controlar su funcionamiento.
Pero su potencia no solo reside aquí. Quizás el punto más interesante de este framework es la facilidad con la que podemos comunicar nuestra aplicación con los backends gracias a Backbone.sync.
Poco a poco iremos ampliando la funcionalidad de este framework para que finalmente podamos presentarles una pequeña aplicación que aplique todo lo aprendido.
Eventos Globales de Aplicaciones en Titanium utilizando Backbone.js
TitaniumPor Jason Kneen | 539 vistas | Lectura de 3 minutos
Introducción a JavaScript: Fundamentos y conceptos básicos
JavaScriptPor Editorial | 2191 vistas | Lectura de 17 minutos
Facilitando el data-binding con Alloy: Parte 1
TitaniumPor Jason Kneen | 463 vistas | Lectura de 4 minutos