miércoles, 10 de junio de 2015

SlickGrid. Dando formato a las celdas (y II) - Formato avanzado

Artículos anteriores:
SlickGrid. Ejemplo básico (I) - Creando el primer grid
SlickGrid. Ejemplo básico (y II) - Añadiendo funcionalidad
SlickGrid. Dando formato a las celdas (I) - Formato básico

En el último artículo vimos cómo dar tamaño a las columnas y establecer un estilo personalizado tanto para las celdas de datos como las cabeceras a través de hojas de estilo.

Pero aún podemos ir más allá, en lugar de limitarnos a aplicar un estilo a la celda podemos definir el código html que representa el valor de la celda a través de una función de formateo asociada a la propiedad formatter de la columna. La función de formateo recibe cinco parámetros:

  • row: índice de la fila (basado en cero)
  • cell: índice de la columna (basado en cero)
  • value: valor de la celda
  • columnDef: objeto de definición de la columna
  • dataContext: objeto de datos de la fila de la celda

Podemos encontrar algunos ejemplos de funciones de formateo en el archivo slick.formatters.js del paquete de descarga del SlickGrid.

Para nuestro caso voy a crear dos funciones de formato: ColorFomatter para aplicar a la columna color y que devolverá un div con el color indicado, y CurrencyFormatter para aplicar un formateo para campos de moneda y que aplicaré a la columna precio (en realidad lo único que hace es añadir el símbolo del Euro al final, pero para el ejemplo sirve).

Voy a seguir el ejemplo del código de slick.formatters.js extendiendo el namespace Slick con un nuevo objeto Formatters que contenga las diferentes funciones de formateo definidas. Así que me he creado en la carpeta Scripts un nuevo archivo gridformatters.js en el que defino las dos funciones de formateo:

$(function (){
    $.extend(true, window, {
        "Slick": {
            "Formatters": {
                "ColorFormatter": ColorFormatter,
                "CurrencyFormatter": CurrencyFormatter
            }
        }
    });

    function ColorFormatter(row, cell, value, columnDef, dataContext) {
        if (value == null || value == "")
            return "";
        else {
            var color;
            switch (value) {
                case "Black":
                    color = "#000000";
                    break;
                case "Red":
                    color = "#ee0000";
                    break;
                case "White":
                    color = "#ffffff";
                    break;
                case "Blue":
                    color = "#0000ee";
                    break;
                case "Multi":
                    return value;
                    break;
                default:
                    color = value;
            }
            return "<div style=\"width:80%; height:80%; background-color:" +
                color + "; border:solid 1px black\"></div>";
        }
    }

    function CurrencyFormatter(row, cell, value, columnDef, dataContext) {
        if (value == null)
            return "";
        else
            return value.toLocaleString() + " &euro;";
    }

});

En la página FormatoColumnas.html he añadido la referencia al archivo gridformatters.js y establecido la propiedad formatter de las columnas Color y Precio a sus respectivas funciones.

<script src="Scripts/slick.core.js"></script>
<script src="Scripts/slick.grid.js"></script>
<script src="Scripts/gridformatters.js"></script>


......


var columns = [
 { name: "ID", field: "ProductID", id: "ProductID", width: 60, resizable: false
  , headerCssClass: "prKeyHeadColumn", cssClass: "numericCell" },
 { name: "Nº Producto", field: "ProductNumber", id: "ProductNumber", width: 120, resizable: false
  , headerCssClass: "headColumn" },
 { name: "Denominación", field: "Name", id: "Name", width: 250, minWidth: 150, maxWidth: 400
  , headerCssClass: "headColumn" },
 { name: "Color", field: "Color", id: "Color", width: 80, minWidth: 60, maxWidth: 120
  , headerCssClass: "headColumn", formatter: Slick.Formatters.ColorFormatter },
 { name: "Precio", field: "StandardCost", id: "StandardCost", width: 110, minWidth: 80, maxWidth: 170
  , headerCssClass: "headColumn", cssClass: "numericCell", formatter: Slick.Formatters.CurrencyFormatter },
 { name: "Sub", field: "ProductSubcategoryID", id: "ProductSubcategoryID", width: 60, resizable: false
  , headerCssClass: "headColumn", cssClass: "numericCell" }
];

Ahora ya podemos comprobar el efecto de los cambios.

Formato de color y moneda

Además de crear funciones de formato genéricas que podemos utilizar en diferentes lugares de nuestra aplicación también podemos crear funciones más específicas.
Entre los datos del producto mostramos un ID de la subcategoría que, en general, poco o nada va a aportarle al usuario. Así que voy a añadir una nueva columna para mostrar la denominación de la subcategoría a través de una función de formateo.

Primero me crearé una variable subcategories con los nombres de todas las subcategorías. A continuación crearé una función de formateo que devuelva la denominación de la subcategoría a partir de su ID y añadiré la definición de la nueva columna.

var subcategories = [
 { ProductSubcategoryID: 1, Name: "Mountain Bikes" },
 { ProductSubcategoryID: 2, Name: "Road Bikes" },
 { ProductSubcategoryID: 3, Name: "Touring Bikes" },
 { ProductSubcategoryID: 4, Name: "Handlebars" },
 { ProductSubcategoryID: 5, Name: "Bottom Brackets" },
 { ProductSubcategoryID: 6, Name: "Brakes" },
 { ProductSubcategoryID: 7, Name: "Chains" },
 { ProductSubcategoryID: 8, Name: "Cranksets" },
 { ProductSubcategoryID: 9, Name: "Derailleurs" },
 { ProductSubcategoryID: 10, Name: "Forks" },
 { ProductSubcategoryID: 11, Name: "Headsets" },
 { ProductSubcategoryID: 12, Name: "Mountain Frames" },
 { ProductSubcategoryID: 13, Name: "Pedals" },
 { ProductSubcategoryID: 14, Name: "Road Frames" },
 { ProductSubcategoryID: 15, Name: "Saddles" },
 { ProductSubcategoryID: 16, Name: "Touring Frames" },
 { ProductSubcategoryID: 17, Name: "Wheels" },
 { ProductSubcategoryID: 18, Name: "Bib-Shorts" },
 { ProductSubcategoryID: 19, Name: "Caps" },
 { ProductSubcategoryID: 20, Name: "Gloves" },
 { ProductSubcategoryID: 21, Name: "Jerseys" },
 { ProductSubcategoryID: 22, Name: "Shorts" },
 { ProductSubcategoryID: 23, Name: "Socks" },
 { ProductSubcategoryID: 24, Name: "Tights" },
 { ProductSubcategoryID: 25, Name: "Vests" },
 { ProductSubcategoryID: 26, Name: "Bike Racks" },
 { ProductSubcategoryID: 27, Name: "Bike Stands" },
 { ProductSubcategoryID: 28, Name: "Bottles and Cages" },
 { ProductSubcategoryID: 29, Name: "Cleaners" },
 { ProductSubcategoryID: 30, Name: "Fenders" },
 { ProductSubcategoryID: 31, Name: "Helmets" },
 { ProductSubcategoryID: 32, Name: "Hydration Packs" },
 { ProductSubcategoryID: 33, Name: "Lights" },
 { ProductSubcategoryID: 34, Name: "Locks" },
 { ProductSubcategoryID: 35, Name: "Panniers" },
 { ProductSubcategoryID: 36, Name: "Pumps" },
 { ProductSubcategoryID: 37, Name: "Tires and Tubes" }
];
function subcategoryNameFormatter(row, cell, value, columnDef, dataContext)
{
 if (value == null) return "";

 var name;
 for (var subcat in subcategories) {
  if (value == subcategories[subcat].ProductSubcategoryID)
   return subcategories[subcat].Name;
 }
 return "";
}
$(function () {
 var columns = [
  { name: "ID", field: "ProductID", id: "ProductID", width: 60, resizable: false
   , headerCssClass: "prKeyHeadColumn", cssClass: "numericCell" },
  { name: "Nº Producto", field: "ProductNumber", id: "ProductNumber", width: 120, resizable: false
   , headerCssClass: "headColumn" },
  { name: "Denominación", field: "Name", id: "Name", width: 250, minWidth: 150, maxWidth: 400
   , headerCssClass: "headColumn" },
  { name: "Color", field: "Color", id: "Color", width: 80, minWidth: 60, maxWidth: 120
   , headerCssClass: "headColumn", formatter: Slick.Formatters.ColorFormatter },
  { name: "Precio", field: "StandardCost", id: "StandardCost", width: 110, minWidth: 80, maxWidth: 170
   , headerCssClass: "headColumn", cssClass: "numericCell", formatter: Slick.Formatters.CurrencyFormatter },
  { name: "Sub", field: "ProductSubcategoryID", id: "ProductSubcategoryID", width: 60, resizable: false
   , headerCssClass: "headColumn", cssClass: "numericCell" },
  { name: "Subcategoría", field: "ProductSubcategoryID", id: "SubcategoryName", width:200, minWidth: 150, maxWidth: 400
   , headerCssClass: "headColumn", formatter: subcategoryNameFormatter }
 ];

Como podemos ver, las columnas del grid no se tienen que corresponder una a una con los campos definidos en los objetos de datos. Podemos tener campos sin su correspondiente columna o, como en el ejemplo, un campo asociado a varias columnas (eso sí hay que recordar que el id de la columna sí debe ser único).

Si recargamos la página veremos la nueva columna con la denominación de la subcategoría.

Columna denominación subcategoría

El código


Puedes descargar el código de todos los ejemplos de SlickGrid de:



Artículo siguiente:
SlickGrid. Habilitando la edición (I) - La teoría

No hay comentarios:

Publicar un comentario