Le applicazioni web utilizzano delle architetture che permettono di separare la logica dell’applicazione dal livello presentazione, dunque i template grafici. Progetti complessi che coinvolgono molti file HTML e molte operazioni di manipolazione attraverso Javascript possono risultare difficili da mantenere. In uno scenario del genere può dunque essere proficuo l’utilizzo di un sistema di template per aumentare la riusabilità del codice.

mustache js

Mustache Js fornisce un sistema di template ben documentato in tal proposito. E dal momento che Mustache supporta una moltitudine di linguaggi, non abbiamo bisogno di un sistema di templating differente per la parte server.

In questo articolo cercheremo di coprire i concetti base di Mustache.

Perchè abbiamo bisogno di un sistema di Template

La maggior parte degli sviluppatori che non sono al corrente dei sistemi di templating non fanno altro che inserire dinamicamente del codice HTML nel DOM della pagina usando JavaScript. Un modo comune per farlo è quello selezionare un elemento e settare la proprietà innerHtml oppure usare il metodo html() di jQuery.

Un esempio di questa tecnica è mostrata sotto:

var html = "<div><span>Evidenziato</span><span>Autore</span></div>";
 
document.getElementByID("container").innerHTML = html;

Un altro metodo per costruire il DOM è quello di creare gli elementi e aggiungerli individualmente:

var titolo = document.createElement('div');
var highlight = document.createElement('span');
var highlight_text = document.createTextNode("Highlight");
var autore = document.createElement('span');
var author_text = document.createTextNode("Author");
var container = document.getElementById('container');
 
highlight.appendChild(highlight_text);
title.appendChild(highlight);
author.appendChild(author_text);
title.appendChild(autore);
container.appendChild(titolo);

Entrambi i metodi sopra possono essere usati per aggiungere efficacemente degli elementi nel vostro documento. Ma se considerassimo una situazione in cui abbiamo una lista di elementi, che dev’essere usata in modi differenti su 3 pagine diverse, in quest’ottica, dovremo ripetere il codice HTML in ben 3 locazioni. Questa è una pratica di programmazione scorretta.

In uno scenario del genere piuttosto potremmo utilizzare dei template predefiniti senza dover ripetere il codice. Mustache.js è il template engine scritto appositamente per un utilizzo tramite javascript.

Iniziare con Mustache.js

Mustache è un sistema di template open source e logic-less sviluppato per linguaggi come JavaScript, Ruby, Python, PHP e Java. Potete ottenere una copia della libreria dalla repository ufficiale, oppure se vi necessita il templating lato server con PHP, si può usare Composer (con un require:”mustache/mustache”).

Mustache fornisce le così dette viste, ed i template. Le viste contengono i dati che vogliamo inserire all’interno dei template, e son formattate usando una specifica sintassi JSON. I template contengono invece il codice di presentazione HTML. Abbiamo detto che Mustache è Logic-less, questo vuol semplicemente dire che Mustache non implementa alcun tipo di costrutto if-else o cicli for.

Partiamo dunque mostrando un semplice esempio:

<!doctype html>
<html lang="it">
  <head>
    <title>Mustache.js metodo in linea</title>
    <script type="text/javascript" src="mustache.js" ></script>
    <script>
      var vista = {
        nome : "Rocco",
        occupazione : "Web Developer"
      };
 
      function loadtemp(){
        var output = Mustache.render("{{nome}} è un  {{occupazione}}", vista);
        document.getElementById('persona').innerHTML = output;
      }
    </script>
  </head>
  <body onload="loadtemp()" >
    <p id="persona"></p>
  </body>
</html>

La prima cosa che viene fatta, è includere nel documento il file mustache.js, dopo possiamo lavorare sulla creazione dei template. Nell’esempio sopra abbiamo una vista contenente il nome e l’occupazione di una persona. Dopo, abbiamo un template all’interno della funzione render(), che presenterà i dati nel template designato.
I Tags di Mustache sono le parentesi graffe, che possono essere 2 o più (con 3 parentesi graffe, “{{{prova}}}”, il contenuto della vista prova viene renderizzato senza fare un escape dei tag HTML). L’uso delle graffe è ciò da cui scaturisce il nome Mustache!

La funzione render() accetta 3 parametri. I primi 2, template e view sono obbligatori, il terzo partials opzionale. Quest’ultimo in particolare può essere considerato come un template dinamico da poter iniettare nel template principale. Nell’esempio precedente, abbiamo passato il template come un parametro in linea alla funzione render, e la vista come secondo parametro. Infine assegnato il risultato alla variabile output.

Writer.prototype.render = function (template, view, partials) {
  return this.compile(template)(view, partials);
};

Questa è la forma base di templating con Mustache. Adesso andiamo a vedere altri metodi disponibili per la creazione di un codice più organizzato.

Definire dei Template con Mustache

Ci sono vari metodi per definire dei template con Mustache nella vostra applicazione. Questi metodi sono simili all’inclusione di file CSS attraverso l’uso dei tag style, l’inline stylesheets e l’external stylesheets. L’esempio visto sopra può essere considerato come un metodo “in linea” dal momento che stiamo passando il template direttamente alla funzione di rendering. D’altronde questo metodo previene la possibilità di riutilizzare i template! Vediamo le alternative:

Template come script in linea

Possiamo definire il template all’interno di un tag script e includerlo all’interno di un documento HTML. Per evitare che browser esegua il codice del template, dobbiamo cambiare il MIME type in qualcosa di diverso dal text/javascript. Alcuni tipi di MIME comuni sono text/html, text/template, e text/mustache.
Ecco un esempio:

<script id="template_esempio" type="text/html">
<h1>{{nome}}</h1>
</script>

Potete includere quanti template volete in un documento, a patto che abbiano un ID differente. Quando vorrete usare il template, ottenete l’HTML all’interno del tag script usando innerHTML, e passatelo come fosse un template:

<script type='text/javascript'>
  var template = document.getElementById('template_esempio').innerHTML;
  var output = Mustache.render(template, vista);
  document.getElementById('persona').innerHTML = output;
</script>

Come facilmente si può osservare, i template sono salvati separatamente e usati dinamicamente all’occorrenza. Questo metodo aumenta le possibilità di riuso. Tuttavia, usando gli script in linea, si limita lo “scope”, la “visibilità” alla singola pagina che mantiene il template. Se aveste più pagine dovreste ridefinire il template nuovamente. Quindi la soluzione ideale è quella di inserire il template in un file esterno, proprio come accade con i fogli di stile CSS.

Template come file HTML esterni

Per mostrare questa tecnica, andremo ad usare jQuery. Quest’ultimo offre una funzione chiamata load(), che può essere usata per ottenere parti di un documento esterno. Useremo questo metodo proprio per ottenere dinamicamente i template posti su file esterni. La peculiarità della funzione load() è che esegue gli script invece di restituirli così come sono, quindi non useremo più i tag html script come fatto nell’esempio precedente. Piuttosto ecco un esempio di template HTML che andremo ad usare:

<div id="template1" >
<h1>{{name}}</h1>
</div>
 
<div id="template2" >
<div>{{name}}</div>
</div>
 
<div id="template3" >
<p><span>{{name}}</span></p>
</div>

Abbiamo usato gli elementi div per il template invece dei tag script. Nell’esempio sopra abbiamo 3 template differenti con 3 ID differenti. Dunque vediamo come utilizzarli all’interno delle nostre pagine:

<!doctype html>
<html lang="it">
  <head>
    <title>Mustache.js Metodo con File Esterni</title>
    <script type="text/javascript" src="jquery.js" ></script>
    <script type="text/javascript" src="mustache.js" ></script>
    <script>
      $(document).ready(function(){
        var view = {
          name : "Rocco",
          occupation : "Web Developer"
        };
 
        $("#templates").load("template.html #template1",function(){
          var template = document.getElementById('template1').innerHTML;
          var output = Mustache.render(template, view);
          $("#person").html(output);
        });
      });
    </script>
  </head>
  <body>
    <p id="person"></p>
    <div id="templates" style="display: none;"></div>
  </body>
</html>

jQuery inserisce il documento restituito da load() all’interno di un elemento HTML piuttosto che assegnarlo ad una variabile, quindi abbiamo bisogno di un container HTML che possa ospitarlo, che nel nostro caso è il div con ID=”templates”, nascosto di default. Nell’esempio sopra dal file template.html viene preso solo il template1. A seconda della necessità si possono prendere altri template o più template. Potenzialmente nulla ci vieta di prendere i template dal server in modo asincrono effettuando una richiesta AJAX.

Conclusioni

I template engine e i framework sono importanti per la gestione di sistemi complessi dove il livello di presentazione è soggetto a frequenti cambiamenti. Mustache.js è una delle migliori scelte per la gestione di template lato client e come già ripetuto esiste anche per linguaggi lato server. Abbiamo esplorato varie tecniche per l’utilizzo dei template, tuttavia tenete presente che Mustache offre molte altre caratteristiche interessanti, come le variabili, le sezioni, i parziali e le funzioni, usate per template più complessi e raffinati. Se volete dunque approfondire la questione, consigliamo la documentazione ufficiale sulla pagina di GitHub.