Estudio del sistema de plantillas Javascript Handlebars, análisis de las posibilidades de las plantillas, sintaxis, estructuras de control, tutorial, etc.
En los artículos anteriores del Manual de Handlebars hemos podido conocer qué nos ofrecen los sistemas de plantillas Javascript y cómo dar los primeros pasos con Handlebars. Ahora vamos a estudiar más de cerca esta librería de plantillas Javascript para entender su funcionamiento.
Comenzamos por observar en las plantillas los bloques delimitados por {{ }} dos llaves de inicio y dos llaves de cierre. Esa forma de abrir y cerrar un bloque en la plantilla es la que da nombre a la sintaxis que utiliza "Mustache".
Insertar valores en las plantillas
Los valores simples se insertan el en código HTML de una plantilla comenzando por {{ y terminando por }}.
{{valor}}
Aunque también se pueden usar tres llaves a la vez, en cuyo caso no escapará el código HTML que haya en el valor.
{{{valor}}}
Insertar expresiones de bloque
Los bloques permiten escribir algunas estructuras de control sencillas, como bucles. Su sintaxis es simuilar a los datos, pero utiizamos además una "#" para abrir el bloque y "/" para terminarlo.
{{# each Beers}} ... {{/each}}
Esto nos va a permitir ejecutar templates en un contexto distinto al del original. Luego lo veremos exactamente. Entre los bloques disponibles tememos:
- each {{# each expresion}} Itera sobre cada elemento de expresión y genera el template asociado. El elemento por el que se itera pasa a ser el nuevo contexto.
- if {{if expresion}} Si expresion devuelve false, undefined, "", null o [] NO renderiza el bloque. Admite {{else}}.
- Unless {{#unless expresion}} esto, al contrario que if, renderiza el bloque si expresion devuelve false, undefined, null, "" o [].
Las propiedades del objeto JSON son perfectamente navegables, accediendo al nombre {{name}}, pero también a compuestas en notación de objeto, como {{author.name}}. Incluso podemos hacer el paso contrario e irnos al contexto padre con {{../name}}, siendo "name" una propiedad encontrada en el contexto padre.
Helpers en Handlebars
También tenemos disponible la figura de los "Helpers", que nos ayudan a registrar nuestras propias funciones para hacer cosas más concretas y repetitivas. Podemos entender los helpers como una extensión del propio sistema de plantillas Handlebars, y son como funciones que se pueden referenciar desde cualquier template. Permiten ejecutar código para dar mayor funcionalidad a las plantillas y así modificar/combinar datos del contexto.
{{fullName author}} invoca al helper fullName pasándole la propiedad author del contexto.
Se registran y se crean helpers propios con Handlebars.registerHelper(), con código como el siguiente:
Handlebars.registerHelper('Italize', function (value) {
return new Handlebars.SafeString("<em>" + value + "</em>");
})
Para crear un helper siempre usamos el método "registerHelper", indicando como primer parámetro el nombre del helper, seguido de un segundo parámetro que es la función del helper propiamente dicho. En esa función recibimos además datos que podemos usar dentro del código del helper y cuyos valores le pasamos desde el código de la plantilla.
Por ejemplo, el helper anterior llamado "Italize" se podría invocar desde la plantilla con el siguiente código:
{{# each Beers}}
Name: {{Name}} - Abv: {{Italize Abv}} <br />
{{/each}}
Podemos ver el código fuente del ejemplo segundo de Handlebars, que hace uso del anterior helper.
!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Beer List</title>
<link href="Site.css" rel="stylesheet" />
<script src="handlebars.js"></script>
<script src="jquery-2.0.0.min.js"></script>
<script type="text/x-handlebars-template" id="template">
{{# each Beers}}
Name: {{Name}} - Abv: {{Italize Abv}} <br />
{{/each}}
</script>
</head>
<body>
<div id="content" style="display:none;">
<strong>Our Beers...</strong><br/>
</div>
<script type="text/javascript">
(function() {
Handlebars.registerHelper('Italize', function (value) {
return new Handlebars.SafeString(
"<em>" + value + "</em>");
});
})();
$(function() {
var stemplate = $("#template").html();
var tmpl = Handlebars.compile(stemplate);
var xhr = $.ajax({
url: '/api/Beers'
});
xhr.done(function (data) {
var ctx = {};
ctx.Beers = data;
var html = tmpl(ctx);
$("#content").append(html);
$("#content").show();
});
});
</script>
</body>
</html>
Si te fijas en el código fuente del ejemplo del artículo anterior de este manual, encontrarás que el Javascript que usamos para compilar la plantilla, invocar al backend para traernos por AJAX el JSON y ejecutar la plantilla, es muy parecido. Realmente esto es normal, porque todo ese proceso no variará apenas en los distintos ejemplos que hagamos. Lo que encontrarás que varían son las plantillas y los helpers que podamos construir.
Recuerda que el JSON es el mismo en todos los ejercicios que hemos realizado sobre Handlebars y que lo puedes ver en: www.desarrolloweb.com/articulos/ejemplos/handlebars/Beers.json
Ejemplo con bloque IF
Ahora podemos ver cómo sería una plantilla que tiene un bloque "if", para mostrar solamente los contenidos que tengan unas caraterísticas.
{{# each Beers}}
{{# if Favorite}}
Name: {{Name}} - Abv: {{Italize Abv}} <br />
{{/if}}
{{/each}}
Con esto conseguimos que solo se impriman aquellas cervezas que se han maracado como "Favorite".
Ejemplo de helper más elaborado
En nuestro trabajo con helpers encontaremos casi siempre casos más claros donde el uso de estas funciones nos ahorrarán más código. Por ejemplo, a partir de un boleano podemos mostrar un icono que simbolice cierto estado.
Handlebars.registerHelper('ShowStar', function (value) {
if (value) {
return new Handlebars.SafeString("<img src='favorite.png' alt='i love this beer!'/>");
} else
return "";
});
En este Helper se usa el parámetro "value" para cargar datos que será un boleano en el objeto JSON. En caso positivo muestra una imagen de un icono y en caso negativo no muestra nada.
Lo podríamos usar desde una plantilla como esta:
{{# each Beers}}
Name: {{Name}} - Abv: {{Italize Abv}} {{ShowStar Favorite}}
<br />
{{/each}}
Otra posibilidad interesante es que podríamos tener, por ejemplo, un helper que convirtiese un nombre de usuario Twitter en un enlace a su perfil.
Handlebars.registerHelper('Twitter', function (value) {
return new Handlebars.SafeString('<a href="http://twitter.com/' + value.substr(1) + '">' + value + '</a>');
});
Fíjate que este helper tiene ya cierta complejidad, porque hacemos un tratamiento Javascript al "value", para quitarle la "@" de un usuario Twitter. Para transformar un dato usamos el método de String "substr()", con lo que demostramos que cuando se está programando un helper no solamente se pueden mostrar datos de nuestro jSON tal cual, sino también se pueden transformar antes de presentar en la página.
Podríamos usarlo ya desde una plantilla como esta:
<ul>
{{# each Beers}}
<li>Name: {{Name}} - Abv: {{Italize Abv}} {{ShowStar Favorite}}
<p>Drinked by: {{Twitter LastCheckin.Drinker}} at {{LastCheckin.When}}</p>
</li>
{{/each}}
</ul>
Eduard Tomàs
Apasionado de la informática, los videojuegos, rol y... la cerveza. Key Consulta...