Backgrid es un componente Datagrid para el framework Backbone, pensado para construir widgets datagrid que sean semánticos y fácilmente adaptables. Al igual que al trabajar en el framework Backbone, la filosofia de este componente es que las tareas comunes sean fáciles de llevar a cabo, y a su vez posibilitar la realización de tareas difíciles o más especializadas posibilitando una fácil personalización y extensión de sus elementos.
Las principales ventajas de Backgrid son las siguientes:
-
Poca o nula curva de aprendizaje, ya que trabaja con simples modelos, colecciones y vistas de Backbone así que si ya estamos familiarizados con este framework no nos costará nada hacernos con el componente.
-
Vista fácilmente personalizable. Al ser el template una tabla HTML es muy fácil de customizar los estilos via CSS, ya sea a nivel de cabecera (th) o fila (tr).
-
Totalmente modular. Por supuesto, al igual que Backbone, es super liviano (lightweight) pero fácilmente extensible.
Demo: Datagrid con listado de Libros
Vamos a ver un mini ejemplo muy reducido con tan solo seis filas pero esperamos que sea ilustrativo para ver cómo funciona el componente. El valor de cada celda se puede editar haciendo click sobre ella, y al hacerlo sobre la cabecera podemos ordenar los datos en función de los valores, excepto en el caso de la columna Imagen, que para esta demo hemos pensado que no tenía mucho sentido esta funcionalidad. Demo en funcionamiento:
El Modelo
El modelo que hemos utilizado para este ejemplo va a ser el mismo que usamos en las otras demos de los frameworks JavaScript. El objeto JSON con los datos que vamos a cargar del server será:
[ { 'id': 1, 'titulo': 'El Juego de Ender', 'autor': 'Orson Scott Card', 'editorial': 'Ediciones B / Zeta', 'img': 'img/img1.jpg' }, { 'id': 2, 'titulo': 'Juego de tronos', 'autor': 'George R. R. Martin', 'editorial': 'Gigamesh', 'img': 'img/img2.jpg' }, { 'id': 3, 'titulo': 'I robot', 'autor': 'Isaac Asimov', 'editorial': 'Edhasa', 'img': 'img/img3.jpg' }, ... ]
Para cargar el modelo, tan solo tenemos que definir la URL desde donde fetchearemos del server. El código es exactamente igual que al cargar un modelo de Backbone.js (que, de hecho, es lo que estamos haciendo!):
var Libro = Backbone.Model.extend({}); var Libros = Backbone.Collection.extend({ model: Libro, url: "data/libros.json" }); var libros = new Libros(); //cargamos modelo libros.fetch(); //Inicializamos Datagrid var datagrid = new Backgrid.Grid({ columns: columns, collection: libros });
Una vez hemos definido el modelo y las columnas que vamos a visualizar, podemos inicializar el objeto Backgrid, que se comportará como una Backbone.View. De esta manera, posteriormente el modelo se cargará de forma totalmente asíncrona desde el server y nuestro objeto datagrid se actualizará con los datos.
Las Celdas
Backgrid viene por defecto con 10 tipos de celda predefinidos, con comportamientos y formatos asociados según el tipo de datos que pueden contener. Las celdas son editables por defecto al clickarlas, y la mayoría contienen algún tipo de lógica para presentar sus datos de manera legible y friendly para personas humanas. Para información más exhaustiva, os recomendamos por supuesto echarle un ojo a la API de las celdas.
Por supuesto, podemos customizar extensivamente estos elementos, por ejemplo un NumberCell adaptado al formato locale hispano de números (que sería el contrario que el anglosajón, es decir coma para separar decimales y punto para separar los miles, millones etc) puede definirse así:
//Extendemos NumberCell para adaptarla //al formato locale hispano cell: Backgrid.NumberCell.extend({ orderSeparator: '.', decimalSeparator: ',' })
Es además muy sencillo utilizar objetos formatters para definir y adaptar estos tipos de celda añadiendo comportamientos adicionales que necesitemos. Por poner un ejemplo, en nuestra demo hemos decidido que vamos a mostrar en el front los títulos de los libros en mayúsculas, independientemente de cómo nos vengan en en modelo desde el server. Para ello, hemos definido un objeto formatter que simplemente debe implementar un método fromRaw para formatear los datos que nos vienen en el modelo, y otro toRaw para quitar el formato que hemos añadido y que no se guarde en el server.
//Extendemos StringCell para asginarle un obj formatter custom cell: Backgrid.StringCell.extend({ formatter: { toRaw: function(formattedValue) { return formattedValue.toLowerCase(); }, fromRaw: function(rawValue) { return rawValue.toUpperCase(); } } })
Por supuesto las celdas al fin y al cabo extienden de la clase Backbone.View, así que podemos modificar totalmente cómo se renderizan definiendo templates para la clase e implementando el método render, como haríamos con cualquier View de Backbone.
En nuestro caso hemos utilizado este sistema para conseguir que aparezcan en el DataGrid las imágenes thumbnail de los libros, para lo que nos hemos definido una mini-plantilla de Underscore.
//Extendemos StringCell para asignar una template custom //en este caso, img tag cell: Backgrid.StringCell.extend({ template: _.template('<img width="32" height="50" src="<%= img %>" />'), render: function() { this.$el.html(this.template(this.model.attributes)); return this; } })
Como podéis observar, un sistema realmente potente que nos permitirá en todos los casos encontrar una celda que se adapte a nuestras necesidades, o customizarla de manera simple y efectiva si lo necesitamos.
Demo: Datagrid con extensión Paginator
¿Qué sería de un componente datagrid si no soportara paginación de los datos? Por supuesto Backgrid tiene una extensión pensada para esta tarea. Para utilizarla, debemos definir nuestra colección de datos como Backbone.PageableCollection que es una genial extensión de Backbone.Collection con funcionalidad adicional de paginación realizada por el mismo autor de Backgrid.
En este componente es el modelo el que debe que proveer, además de los datos, la información necesaria para las funciones de paginación, es decir la página actual, el número de items por página a mostrar y el número total de items, pero podemos personalizar el comportamiento para que la paginación se produzca en el cliente (es decir el server nos mandará un json con todos los datos) o en el server (y tendré que recuperar los datos de las diferentes páginas en sucesivas peticiones al server). El objeto JSON que recibimos del server quedaría por tanto así:
[ { 'per_page': 2, 'total_entries': 6, 'total_pages': 3, 'page': 1 }, [ { 'id': 1, 'titulo': 'El Juego de Ender', 'autor': 'Orson Scott Card', 'editorial': 'Ediciones B / Zeta', 'img': 'img/img1.jpg' }, { 'id': 2, 'titulo': 'Juego de tronos', 'autor': 'George R. R. Martin', 'editorial': 'Gigamesh', 'img': 'img/img2.jpg' }, ... ] ]
El resto del código del modelo quedaría igual, excepto el detalle antes mencionado de que en este caso nuestra colección de datos deberá extender de Backbone.PageableCollection
//Inicializamos Datagrid, con paginación //en el elemento footer var datagrid = new Backgrid.Grid({ columns: columns, collection: libros, footer: Backgrid.Extension.Paginator });
Y por último la inicialización del objeto Backgrid en la que añadimos un elemento footer que contendrá la extensión paginator con las funciones esperadas de paginación. Great! 🙂
Conclusión
Esperamos que este componenete os haya parecido interesante, nos parece que se le puede sacar mucho jugo por la potencia que tiene y su facilidad de customización, ya sea mediante la adaptación de los elementos existentes o creando nuevas funcionalidades mediante extensiones. En resumen, una pequeña joya para nuestras aplicaciones JavaScript.
Excelente explicación y tutorial, tengo una duda, ¿como podría conectarme a una base de datos mysql?