Aprendiendo a usar Handlebars como sistema de templates en jQuery

Hace tiempo que empecé a ver que en algunas de mis aplicaciones, hago demasiadas manipulaciones al DOM de manera manual o guardo muchas cadenas de HTMl como si fueran simples cadenas de texto. Al principio, todo va bien pero cuando el código comienza a crecer se hace muy difícil de mantener.

Recientemente tratamos el tema de cómo añadir elementos al DOM con jQuery de manera elegante, y ya en este artículo dejaba a entrever que lo más óptimo es usar un sistema de plantillas (templates) de JavaScript. He trabajado con un par de ellos pero hoy voy a ha hablaros de Handlebars. Handlebars es una extensión de Mustache.js que tiene más prestaciones y mejor rendimiento. Si alguna vez hiciste algún template en Mustache.js no hay problema peusto que es compatible con Handlebars. Mustache tiene muchas implementaciones en muchos lenguajes de programación y es usado en multitud de sitios. Si queréis, podéis descubrir un poco más sobre Mustache en su web en Github.

¿Por qué un sistema de plantillas?

Un sistema de plantillas permite definir de manera muy sencilla una “plantilla” para datos que vas a mostrar en el navegador para ser más limpio y legible que el común método de concatenar cadenas de caracteres dentro de una matriz mientras recorres un objeto que acabas de recibir (o crear) del servidor.

¿Y qué es una plantilla en sí? Bueno, las plantillas son código del lado del cliente que tienen expresiones para que la plantilla pueda recibir un objeto o una colección de ellos para renderizarlos fácilmente en código HTML.

Además, si trabajamos con diseñador, le resultará más sencillo modificar estas plantillas sin tener que enredar con el propio código.

Instalando Handlebars

La forma más sencilla de instalar Handlebars.js es descargar la última versión del proyecto en Github, que actualmente va por la beta 6 de la versión 1.0. La inclusión es similar a la que haríamos con cualquier script:

Ejemplos

Handlebars es realmente sencillo de usar y en los ejemplos que usaré para acompañar la explicación, veréis que la propia plantilla queda encapsulada en una etiqueta script con un tipo que el navegador no puede reconocer x-handlebars-template. Las variables y expresiones en Handlebars van encapsuladas entre dos llaves {{ y }}.

Como Hola mundo es demasiado popular, vamos a empezar con un… Hola Función 13.

Ejemplo 1 – Hola mundo Función 13

Esta es nuestra plantilla:

<script id="nuestra-plantilla" type="text/x-handlebars-template">  
  <p>Hola {{usuario}}</p>
</script>  

Ahora tenemos que compilar la plantilla:

var fuente = $('#nuestra-plantilla').html();  
var plantilla = Handlebars.compile(fuente);  

Ahora tenemos que pasar los datos, para ello voy a incluirlo en una variable, pero esta puede venir de cualquier sitio. Posteriormente vamos convertirla en HTML y adjuntarla al DOM.

var datos = {  
  usuario: 'Función 13'
};
var html = plantilla(datos);  
$('#contenido').html(html);

Lo cual resulta en:

<p>Hola Función 13</p>  

Puedes ver la demo. A partir de ahora, usaremos el mismo esquema y tan solo mostraremos y explicaremos los cambios a la propia plantilla y al objeto datos.

Ejemplo 2 – Una lista

En el siguiente ejemplo vamos a ir un poco más lejos y vamos a iterar sobre un objeto JavaScript creando una lista de usuarios. Quizá este sea el uso más común:

<ul> {{#each this}}  
  <li>
    <strong>Usuario</strong>: {{nombre}}
    <ul>
      <li>
        <strong>Edad</strong>: {{edad}}</li>
    </ul>
  </li> {{/each}} 
</ul>  

Y los datos:

var datos = [{  
  nombre: 'Matusalén',
  edad: 'Desconocida'
}, {
  nombre: 'Madonna',
  edad: 60
}];

Tendremos lo que buscábamos:

<ul>  
  <li>
    <strong>Usuario</strong>: Matusalén
    <ul>
      <li>
        <strong>Edad</strong>: Desconocida</li>
    </ul>
  </li>
  <li>
    <strong>Usuario</strong>: Madonna
    <ul>
      <li>
        <strong>Edad</strong>: 60</li>
    </ul>
  </li>
</ul>  

El bloque each, lo que hace es iterar sobre cada objeto (en este caso le pasamos como contexto el objeto completo this) y usar los datos que le estamos facilitando.

La demo se puede ver aquí.

Ejemplo 4 – Bloques

Algunas veces es útil separar la paja de la avena y centrarnos en datos específicos en particular. Por ejemplo, imaginad el siguiente origen de datos:

var datos = {  
  animados: [{
    nombre: 'Homer'
  }, {
    nombre: 'Rasca'
  }, {
    nombre: 'Peter'
  }, {
    nombre: 'Stewie'
  }],
  dibujante: 'Matt Groening'
};

Para representarlos podríamos usar una expresión de bloque. Los bloques se representan en Handlebars como una almohadilla # y son seguidos por una expresión. Si la expresión se evalúa como matriz, Handlebars iterará de manera automática sobre cada elemento de la matriz, estableciendo el contexto actual a ese elemento.

Veamos:

<ul>  
  {{#animados}}
  <li>{{nombre}} - {{../dibujante}}</li> 
  {{/animados}} 
</ul>  

Teniendo en cuenta que los bloques cambian el contexto, Handlebars nos permite usar la expresión ../ para acceder al contexto superior por lo que, de esta manera, podemos acceder a la propiedad dibujante que quedaba fuera de la matriz de animados:

<ul>  
  <li>Homer - Matt Groening</li>
  <li>Rasca - Matt Groening</li>
  <li>Peter - Matt Groening</li>
  <li>Stewie - Matt Groening</li>
</ul>  

Puedes ver la demo aquí.

Conclusión

Handlebars tiene mucho más que ofrecer y esto es solo el principio. En próximos artículos trataremos las partes más avanzadas de este sistema de plantillas como los bloques if, unless y cómo crear nuestras propias funciones.

Programador Front-end en First + Third y Potato. Trabajando con JavaScript y HTML5 desde el corazón de Sevilla.