What's a templating engine? Describe what it does… →
A templating engine is software/an application/a library that:
In our case, we're using a templating library called handlebars:
Why bother using templating? We were able to emit html directly by using res.end("<html>...") or res.send("<html>...")
?
Using a templating engine that's decoupled from your application's logic is useful because: →
Install:
npm install hbs --save
Configure using app.set (see other configurations you can set)
app.set('view engine', 'hbs');
hbs directory structure →
views/layout.hbs
views/index.hbs
When a template is rendered using res.render
, there are two arguments. →
The view or template to render… and the context object.
The context object's properties are available to your template as variable names!
// the second argument is an object
res.render('myview', {'item':'pizza', 'description':'tasty'});
{{ description }} {{ item }}
tasty pizza
Just use double curly braces (no spaces) to drop a value in your context into your template!
But what about some logic. What if the value that I'm passing in is an array or object? →
Handlebars actually has some basic facilities for:
From the handlebars docs
Block expressions allow you to define helpers that will invoke a section of your template with a different context than the current
{{#helper}}stuff{{/helper}}
The #each
helper:
#each
, you can use {{this}}
or {{.}}
to output the current item
In your application: →
app.get('/templating-arrays', function(req, res) {
res.render('templating-arrays', {'luckyNumbers':[42, 7, 78, 3, 5]});
});
In your view: →
<ul>
{{#each luckyNumbers}}
<li>{{this}}</li>
{{/each}}
</ul>
Handlebars allows named block parameters, which allows you to give each element a name while iterating: →
{{#each words as |word|}}
<p>word again: {{word}}</p>
{{/each}}
In your application: →
app.get('/templating-objects', function(req, res) {
res.render('templating-objects', {'obj':{'topping':'mushroom', 'size':'medium'}});
});
In your view, use this
to get the value: →
<ul>
{{#each obj}}
<li>{{this}}</li>
{{/each}}
</ul>
Assuming this context object (cat is an object):
{cat: {name:'bill furry', lives:9}};
If you want both the key and the value, use @key
and this
→
<ul>
{{#each cat}}
<li>{{@key}}, {{this}}</li>
{{/each}}
</ul>
Assuming this context object (points is an Array of objects):
{points: [{x:1, y:2, z:3}, {x:21, y:34, z:55}]}
Use dot notation to access properties:
<ul>
{{#each points}}
<li>{{this}}, {{this.x}}, {{this.y}}, {{this.z}} </li>
{{/each}}
</ul>
Or just the property name!
<ul>
{{#each points}}
<li>{{x}}, {{y}}, {{z}}</li>
{{/each}}
</ul>
(Note - no equality operators 4 U) …
{{#if isActive}}
{{else}}
{{/if}}
By the way, if you see something like:
Expecting 'ID', 'DATA', got 'INVALID'
You probably have spaces in your {{ #helper }}
.