Utilizando librerías de JS externas en nuestro módulo de Drupal 8

Y haciéndolo de la manera correcta

Gráfico resultante con nuestro ejemplo de Chart.js

This post is also available in english here.

Para hacer esto en Drupal 7 utilizábamos el módulo libraries. En Drupal 8, esta sigue siendo la forma correcta de hacerlo; sin embargo, este módulo está en proceso de un cambio enorme y no está del todo bien documentado en este momento, por ello hacerlo la primera vez fue todo un reto.

Para este post, vamos a integrar la librería Chart.js en un bloque en nuestro Drupal. Lo primero que necesitamos es obviamente descargar e instalar el módulo libraries. Una vez hecho eso, de acuerdo con la documentación necesitamos revisar si hay una definición de nuestra librería en el registro de librerías; si esta existe y nos funciona, nos ahorramos un paso. Si no existe (tal fue mi caso), debemos crearla (y por supuesto intentar contribuirla). Para ello, necesitamos un archivo json con la definición de la librería en la carpeta public://library-definitions; en nuestro caso, ese archivo se va a llamar chart_js.json y va a tener el siguiente contenido:

{
"name": "Chart.js",
"type": "asset",
"vendor url": "http:\/\/www.chartjs.org",
"download url": "https:\/\/github.com\/chartjs\/Chart.js\/releases\/latest",
"variants": {
"minified": {
"js": {
"Chart.min.js": "Chart.min.js"
}
}
},
"js": {
"Chart.js": "Chart.js"
},
"version_detector": {
"id": "line_pattern",
"configuration": {
"file": "Chart.js",
"pattern": "\/Version: ([0-9a-zA-Z\\.-]+)\/"
}
}
}

En ese archivo, indicamos el nombre humano de nuestra librería, el tipo (asset en nuestro caso), y otra información de la misma.

Algo importante, es que una vez que hemos probado ese archivo, lo contribuyamos de vuelta a través del issue queue para que en caso de que alguien más necesite esta librería, la pueda obtener automáticamente.

El siguiente paso es descargar nuestra librería en la ubicación correspondiente, la cual según la documentación es sites/all/assets/vendor/<library_name>, en nuestro caso sites/all/assets/vendor/chart_js y allí ponemos los archivos Chart.js y Chart.min.js.

Por supuesto, para utilizar esa librería, necesitamos un archivo propio de javascript; para ello, lo creamos dentro de una carpeta js (simplemente por orden) con el nombre que deseemos. Para este post, vamos a seguir el ejemplo básico de la documentación de la librería y ese archivo va a llamarse demo_chartjs.js y contiene lo siguiente:

(function ($, Drupal) {
Drupal.behaviors.demoChartJsDemoChart = {
attach: function (context, settings) {
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
}
};
})(jQuery, Drupal);

En el archivo anterior no vemos mayor diferencia con respecto a cómo funciona javascript en Drupal 7; sin embargo, si se quiere ampliar más, se puede consultar la respectiva documentación.

Algo importante a notar es que en Drupal 8 lo único que podemos adjuntar a un arreglo de render son librerías, por ende, necesitamos definir una; para ello de acuerdo con la documentación oficial debemos definir nuestra librería en el archivo .libraries.yml. Si nuestro módulo se llama demo_chartjs, este archivo se llamará demo_chartjs.libraries.yml y contendrá lo siguiente:

demo_chartjs:
version: 1.x
js:
js/demo_chartjs.js: {}

A continuación, crearemos un template para hacer render del markup que ocupamos para crear nuestro gráfico; para ello, en el archivo .module vamos a implementar el hook_theme:

/**
* Implements hook_theme().
*/
function demo_chartjs_theme() {
return [
'demo_chartjs_demo_chart' => [
'variables' => [],
],
];
}

Y añadimos nuestro template en una carpeta templates de nuestro módulo con el nombre demo-chartjs-demo-chart.html.twig y el siguiente contenido:

{#
/**
* @file
* Template file for demo_chartjs_demo_chart.
*/
#}
<canvas id="myChart" width="400" height="400"></canvas>

Ahora, lo único pendiente es crear nuestro bloque; para ello, en la carpeta src/Plugin/Block creamos un archivo DemoChartJs.php con el siguiente contenido:

<?php
namespace Drupal\demo_chartjs\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Component\Utility\Xss;
/**
* Provides a 'DemoChartJs' block.
*
* @Block(
* id = "demo_chart_js",
* admin_label = @Translation("Demo chart js"),
* )
*/
class DemoChartJs extends BlockBase {
  /**
* {@inheritdoc}
*/
public function build() {
$build = [];
$build['chart'] = [
'#theme' => 'demo_chartjs_demo_chart',
'#attached' => [
'library' => [
'libraries/chart_js',
'demo_chartjs/demo_chartjs',
],
],
];
    return $build;
}
}

La parte más importante de ese archivo es la función build; en ella estamos diciéndole a Drupal que use el theme demo_chartjs_demo_chart definido previamente como la renderización de nuestro template; y estamos adjuntando dos librerías:

  • libraries/chart_js: La librería de chart_js. Como es una librería externa, siempre se registran como parte del módulo libraries.
  • demo_chartjs/demo_chartjs: Nuestra librería como la definimos en el archivo .libraries.yml que únicamente incluye el archivo javascript.

Con todo lo anterior hecho, ha llegado el momento de probar nuestro bloque; lo añadimos a nuestro sitio y deberíamos tener nuestro gráfico tal como en la imagen que encabeza este artículo.

Disclaimer: el módulo libraries está en pleno desarrollo y algunas cosas podrían cambiar; sin embargo, los conceptos generales no creo que cambien durante este proceso.

Espero que les sea útil.


Manatí es una firma consultora web de origen costarricense, donde hacemos sitios estratégicamente diseñados para llevar organizaciones a lograr objetivos.

No se pierdan los proyectos, noticias e ideas de nosotros en Manatí. Conozca más sobre lo que hacemos, síganos en medium, twitter y facebook.