Visualización de datos con DataTables.js y Highcharts.js
Spanish (Español) translation by Ana Paulina Figueroa (you can also view the original English article)
En este tutorial aprenderás a visualizar datos aprovechando las bibliotecas DataTables.js y Highcharts.js de JavaScript.
Esto es lo que vamos a construir (revisa la versión ampliada para tener una mejor experiencia):
Bibliotecas necesarias
Para los fines de este ejemplo tendremos que cargar las siguientes bibliotecas en nuestro pen:
- jQuery
- DataTables.js
- Highcharts.js
Con eso en mente, si revisas en la pestaña Settings verás que he incluido un archivo CSS externo:



De la misma manera también he incluido cuatro archivos externos de JavaScript:



Nota: tuvimos que agregar jQuery a nuestro proyecto debido a que DataTables.js es un complemento de jQuery. Sin embargo, ten en cuenta que Highcharts.js es una biblioteca pura de JavaScript y por lo tanto no requiere jQuery.
El HTML
Para empezar definimos un elemento con la clase container
, que contiene dos subelementos:
- Una tabla con 26 filas. La primera fila hace referencia a los encabezados
th
de la tabla, mientras que las otras 25 filas contienen detalles sobre los países. La fuente de nuestros datos para este ejemplo es worldometers.info. - Un
div
vacío que contendrá el gráfico.
Esta es la estructura HTML:
<div class="container"> <table id="dt-table"> <thead> <tr> <th>Country</th> <th>Population (2017)</th> <th>Density (P/Km²)</th> <th>Med. Age</th> </tr> </thead> <tbody> <tr> <td>China</td> <td>1,409,517,397</td> <td>150</td> <td>37</td> </tr> <!-- 24 more rows here --> </tbody </table> <div id="chart"></div> </div>
Vale la pena mencionar que, para simplificar las cosas, hemos especificado los datos de la tabla mencionada anteriormente de forma estática. Sin embargo, en un proyecto real la tabla podría crearse dinámicamente.
Con el marcado listo y un color de fondo añadido para mayor claridad, el proyecto se ve así:
El CSS
En este punto definimos algunos estilos básicos, de la siguiente manera:
.container { display: flex; flex-wrap: wrap; align-items: center; padding: 0 10px; } #dt-table_wrapper { width: 35%; margin-right: 2%; } #chart { width: 63%; } table { text-align: left; } @media screen and (max-width: 1200px) { #dt-table_wrapper, #chart { width: 100%; } #dt-table_wrapper { margin-right: 0; } }
Es importante comprender que:
- El
#dt-table_wrapper
no existe en nuestro marcado. Este es añadido por las DataTables tan pronto como las inicializamos. - Si bien definimos algunas reglas básicas para pantallas pequeñas, toma en cuenta que el demo no será totalmente responsivo. Hay muchas cosas que podemos hacer para que la tabla y el gráfico se vean mejor en pantallas pequeñas. Por ejemplo, para DataTables hay una extensión responsiva disponible, pero eso va más allá del alcance de este tutorial.
Con el CSS en su lugar veamos cómo se ve el proyecto. Aún no veremos una gran diferencia porque no hemos inicializado las bibliotecas:
El JavaScript
Ahora veamos la ventana de JavaScript en nuestro pen. Cuando el DOM está listo se ejecuta la función init
; esta función desencadena otras subfunciones:
function init() { const table = $("#dt-table").DataTable(); const tableData = getTableData(table); createHighcharts(tableData); setTableEvents(table); }
Como verás, cada una de estas subfunciones lleva a cabo una determinada tarea.
Inicializando las DataTables
El primer paso es convertir nuestra tabla a una tabla "DataTables". Podemos hacerlo usando solamente una línea de código: $("#dt-table").DataTable();
Si ahora miramos la tabla notaremos que ha adoptado las capacidades de una tabla DataTables, es decir: podemos ordenarla, hacer búsquedas en ella, etcétera. Juega con ella en el siguiente demo:
Ahora, como puedes ver, las DataTables aplican un ordenamiento predeterminado a la tabla. Si es necesario podemos personalizar este comportamiento.
Extrayendo los datos de la tabla
El siguiente paso es tomar los datos de la tabla y construir el gráfico. No queremos todos los datos de la tabla. De hecho, si vuelves a ver la versión finalizada de nuestro demo, podrás notar que el gráfico solamente contiene datos de las primeras tres columnas (País, Población, Densidad).



Con eso en mente, para obtener los datos necesarios aprovecharemos la DataTables API. La función responsable de este comportamiento es la siguiente:
function getTableData(table) { const dataArray = [], countryArray = [], populationArray = [], densityArray = []; // loop table rows table.rows({ search: "applied" }).every(function() { const data = this.data(); countryArray.push(data[0]); populationArray.push(parseInt(data[1].replace(/\,/g, ""))); densityArray.push(parseInt(data[2].replace(/\,/g, ""))); }); // store all data in dataArray dataArray.push(countryArray, populationArray, densityArray); return dataArray; }
Dentro de esta función iteramos a través de las filas de la tabla y, por cada fila, tomamos los datos de la columna destino y los almacenamos en los arreglos asociados. Finalmente, todos estos arreglos se almacenan dentro de otro arreglo.
Esta es una visualización rápida del arreglo maestro (es decir, dataArray
):



Antes de continuar, es importante comprender una cosa. De forma predeterminada la función getTableData
debe recolectar los datos de todas las filas de la tabla. Pero entonces si buscamos algo específico en la tabla solamente las filas que coincidan serán recolectadas y procesadas. Para lograr estas acciones pasamos un argumento a la función rows
. Específicamente un objeto con el valor de propiedad search: "applied"
.
Nuevamente toma en cuenta que si no pasamos este objeto siempre recolectaremos datos de todas las filas de la tabla (haz la prueba). Para más información sobre las propiedades que podemos pasar a este objeto revisa esta página.
Creando el gráfico
Ahora que tenemos los datos que deseamos, estamos listos para construir el gráfico. Este contendrá dos gráficos anidados, un gráfico de columnas y un gráfico de spline.
Esta es la función correspondiente:
function createHighcharts(data) { Highcharts.setOptions({ lang: { thousandsSep: "," } }); Highcharts.chart("chart", { title: { text: "DataTables to Highcharts" }, subtitle: { text: "Data from worldometers.info" }, xAxis: [ { categories: data[0], labels: { rotation: -45 } } ], yAxis: [ { // first yaxis title: { text: "Population (2017)" } }, { // secondary yaxis title: { text: "Density (P/Km²)" }, min: 0, opposite: true } ], series: [ { name: "Population (2017)", color: "#0071A7", type: "column", data: data[1], tooltip: { valueSuffix: " M" } }, { name: "Density (P/Km²)", color: "#FF404E", type: "spline", data: data[2], yAxis: 1 } ], tooltip: { shared: true }, legend: { backgroundColor: "#ececec", shadow: true }, credits: { enabled: false }, noData: { style: { fontSize: "16px" } } }); }
¡No te sientas abrumado por el código anterior! sin duda la mejor forma de comprender cómo funciona es probándolo. Además, definitivamente debes leer la documentación. De cualquier manera, vamos a destacar brevemente los conceptos clave:
- El eje x contiene todos los países.
- Definimos dos ejes y. El primero tiene todos los valores de la población, mientras que el segundo incluye todas las densidades disponibles.
- Si nuestro gráfico no contiene datos aparecerá un mensaje. Toma en cuenta que podemos personalizar el texto del mensaje a través del objeto
lang
.
Con los gráficos en su lugar veamos nuevamente nuestro progreso:
Sincronizando la tabla y los gráficos
En la sección anterior creamos el gráfico en base a los datos de la tabla, pero aún no hay una sincronización completa entre la tabla y el gráfico. Para probar lo anterior, regresa al último demo y cambia el ordenamiento (arreglo) de la tabla o busca algo. Te darás cuenta de que el gráfico no reacciona a los cambios de la tabla.
Para resolver esto aprovecharemos el evento draw
de las DataTables. Este evento se dispara cada vez que la tabla se actualiza. Así que tan pronto como modifiquemos la tabla debemos recolectar los datos de la misma y reconstruir el gráfico.
Aquí está lo complicado. El evento draw
también se dispara durante la paginación de la tabla; no hay razón para reconstruir el gráfico durante este proceso. Idealmente debemos prevenir este comportamiento. Afortunadamente existe el evento page
que nos ayuda a lograr esta tarea.
Este es el código que implementa la funcionalidad deseada:
let draw = false; function setTableEvents(table) { // listen for page clicks table.on("page", () => { draw = true; }); // listen for updates and adjust the chart accordingly table.on("draw", () => { if (draw) { draw = false; } else { const tableData = getTableData(table); createHighcharts(tableData); } }); }
Ahora que tanto la tabla como el gráfico están en sincronía, si hacemos una búsqueda "mala" veremos los siguientes mensajes:



La versión final de nuestro proyecto:
Soporte para navegadores
Ambos complementos cuentan con gran soporte para navegadores (DataTables support, Highcharts support), por lo que puedes esperar que este demo funcione bien en todos los navegadores recientes.
Nuevamente ten en mente que este demo no está optimizado para pantallas pequeñas.
Finalmente, como es costumbre, usamos Babel para compilar el código ES6 a ES5.
Conclusión
¡Eso es todo amigos! logramos visualizar nuestros datos combinando dos populares y poderosas bibliotecas de JavaScript.
Ahora que estás familiarizado con el proceso, ve y elabora la funcionalidad del demo final. Por ejemplo, intenta añadir filtros personalizados a la tabla.
Como siempre, si tienes preguntas o si hay algo más que te gustaría ver como un paso siguiente en este tutorial, házmelo saber en los comentarios que aparecen a continuación.