Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Template HTML (e non solo) per Node.js... con Bind

Un modulo utile a curare sia il front-end delle applicazioni sia a generare "response" di tipo JSON o XML per servizi REST
Un modulo utile a curare sia il front-end delle applicazioni sia a generare "response" di tipo JSON o XML per servizi REST
Link copiato negli appunti

In questa lezione approfondiremo il tema dei template HTML (ma non solo). Questo aspetto è fondamentale per creare applicazioni che siano, oltre che funzionanti, anche visivamente curate e utilizzabili dagli utenti attraverso un browser.

Se nella scorsa lezioni abbiamo creato un modulo ad hoc per svolgere il primo dei compiti richiesti (il dispatching della corretta risorsa sulla base dell'url) in questa lezione utilizzeremo un modulo già esistente. Questa scelta è dettata dal fatto che implementare da zero un motore di rendering non è un compito né breve né soprattutto semplice date le molte variabili in gioco. E dato che ce ne sono di ottimi in circolazione perchè reinventare la ruota?

Il modulo che utilizzeremo si chiama Bind ed è ovviamente disponibile sul repository NPM (npm
install bind
) oltre che sul celeberrimo github. Una volta installato il plugin addentriamoci nello sviluppo.

Negli esempi di questo articolo non ci soffermeremo sui concetti analizzati nelle lezioni precedenti ma ci concentreremo solamente sugli aspetti che non abbiamo ancora affrontato.

Il primo template e l'oggetto context

Utilizzare bind è semplicissimo: il modulo esporta la funzione toFile che permette di compilare il template a partire da un file presente su disco e di elaborarne il risultato in maniera asincrona, in perfetto stile Node.js.

Per compilare un template è necessario definire un oggetto context che conterrà tutti i parametri che si vogliono comunicare al motore di templating. Guardiamo un esempio:

/* file server.js */
dispatcher.onGet('/home', function(req, res, chain) {
    bind.toFile('tpl/home.tpl', {
        name: 'Alberto',
        address: 'via Roma',
        city: 'Milano'
    }, function(data) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(data);
    });
});

/* file tpl/home.tpl */
<h1>(:name ~ Marco:)</h1>
<b>(:address:) - (:city:)</b>

Il primo metodo che node elaborerà è proprio la funzione toFile che compilerà il template presente nella cartella tpl utilizzando l'oggetto composto da name, address e city. La callback dell'elaborazione riceverà il template compilato sottoforma di stringa (data) e, dopo aver settato il corretto codice HTML e content-type, invierà la response al client. L'unica nota da aggiungere è l'utilizzo del carattere tilde (~) per definire un valore di default (nel nostro caso il nome Marco) nel caso la variabile non esistesse.

Una delle caratteristiche interessanti del modulo è la possibilità di invocare funzioni JavaScript direttamente nel template mantenendo però una chiara divisione dei compiti. Eccone esempio di una funzione (plus) che ritorna +1 al valore ricevuto come parametro:

/* server.js */
dispatcher.onGet('/page', function(req, res, chain) {
    bind.toFile('tpl/page.tpl', {
        plus: function(cb, a) {
            return cb(parseInt(a, 10)+1);
        }
    }, function(data) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(data);
    });
});

/* tpl/page.tpl */
Risultato: (:plus ~ 5:)

Ovviamente è possibile passare al template strutture dati più complesse come oggetti o vettori. Per un analisi più approfondita rimando alla documentazione ufficiale su github.

Includere sub-template

Con Bind è possibile definire anche dei sotto template facilmente utilizzabili in diversi contesti. Per includere un file all'interno di un template è sufficiente invocare la funzione :file. Eccone un esempio:

/* padre.tpl */
<h1>Io sono il padre</h1>
(:file ~ tpl/figlio.tpl)

/* figlio.tpl */
<h2>Io sono il figlio</h2>

Il contenuto della pagina inclusa verrà sempre codificato. Per evitare l'auto-encoding si può utilizzare la funzione file^ (con il cappelletto finale).

Controllo del flusso

L'ultima funzionalità presente in Bind è il controllo del flusso tramite il diffusissimo costrutto if-then-else implementabile in questo modo:

/* admin.js */
(:if[admin] ~
    [:then ~ Benvenuto nell'amministrazione :]
    [:else ~ Via di qua! :]
:)

Non solo HTML

Ovviamente con Bind è possibile costruire qualsiasi tipo di "response", quindi anche XML o JSON. La compilazione avviene sempre allo stesso modo; l'unico aspetto da modificare è il content-type della response che deve essere coerente con il tipo di stringa inviata al client. Ecco un esempio

/* server.js */
dispatcher.onGet('/xml', function(req, res, chain) {
    bind.toFile('tpl/xml.tpl', {
        name: 'Alberto',
        city: 'Milano',
        skills: [{
            skill: 'NodeJS',
            grade: 'A'
        }, {
            skill: 'JavaScript',
            grade: 'A',
        }, {
            skill: 'Bash scripting',
            grade: 'B'
        }]
    }, function(data) {
        res.writeHead(200, {'Content-Type': 'text/xml'});
        res.end(data);
    });
});

/* tpl/xml.tpl */
<?xml version="1.0" ?>
<person>
    <name>(:name:)</name>
    <city>(:city:)</city>
        (:skills ~
        <skill>
            <skill>[:skill:]</skill>
            <grade>[:grade:]</grade>
        </skill>
        :)
</person>

Tutto molto semplice e chiaro!

Nel prossimo articolo introdurremo un po' di interazione nelle applicazioni tramite l'utilizzo delle
form e della validazione server-side.

Ti consigliamo anche