I have a handlebars partial that I want to include twice on my page. Once as normal HTML to be parsed and displayed, and once as escaped HTML to be shown to the user (kind of like on the Bootstrap docs as shown in the image below):
In underscore templates it would just be:
{% examples/buttons %}
<code>
{%- examples/buttons %}
</code>
How can I acplish it in Handlebars?
I'm rendering these files on a node.js server and using the built-in partials feature (this doesn't work. I can't figure out what to make the second one look like to tell it to escape the HTML):
{{> examples/buttons }}
<code>
{{> examples/buttons }}
</code>
I have a handlebars partial that I want to include twice on my page. Once as normal HTML to be parsed and displayed, and once as escaped HTML to be shown to the user (kind of like on the Bootstrap docs as shown in the image below):
In underscore templates it would just be:
{% examples/buttons %}
<code>
{%- examples/buttons %}
</code>
How can I acplish it in Handlebars?
I'm rendering these files on a node.js server and using the built-in partials feature (this doesn't work. I can't figure out what to make the second one look like to tell it to escape the HTML):
{{> examples/buttons }}
<code>
{{> examples/buttons }}
</code>
Share
Improve this question
edited Dec 17, 2015 at 16:30
cmcculloh
asked Dec 17, 2015 at 16:23
cmccullohcmcculloh
48.7k42 gold badges108 silver badges137 bronze badges
2
-
2
Handlebars stores the partials you register in
Handlebars.partials
, so you should be able to write a pretty simple block helper to output the contents of a given partial by looking it up in there. – David Brainer Commented Dec 17, 2015 at 17:01 -
For my use case I was able to just use
\{{examples/buttons}}
– Anima-t3d Commented Jan 10, 2018 at 4:25
4 Answers
Reset to default 3Return partial's HTML as text with a custom helper
There is no native syntax for outputting the text-escaped content of a partial, but you can create an expression helper to do that for you.
In the below example, the helper returns the raw piled output of the partial, and even allows you to unescape it with the "triple-stash" {{{
for typical output.
Note, the syntax of the helper isn't as friendly as the native partial syntax, and you must pass in the current context as a parameter:
{{! unescaped HTML output (renders HTML as HTML) }}
{{{output "header" this}}}
{{! escaped HTML output (renders HTML as text) }}
{{output "header" this}}
$(function() {
// Register a helper called "output"
Handlebars.registerHelper('output', function(partial, context) {
// Create piler function for said partial
var output = Handlebars.pile(Handlebars.partials[partial]);
// Return piled output using said context
return output(context);
});
// Register a partial called "header"
Handlebars.registerPartial('header', $("#partial-header").html());
// Create piler function for main template
var template = Handlebars.pile($("#template").html());
// Render piled output as HTML to `#rendered` using provided context (JSON)
$("#rendered").html(
template(
{
"title": "My Cool Header"
}
)
);
});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
<script id="template" type="text/x-handlebars-template">
{{{output "header" this}}}
{{output "header" this}}
</script>
<script id="partial-header" type="text/x-handlebars-template">
<h1>{{title}}</h1>
</script>
<div id="rendered"></div>
I spent hours looking for the solution to this. The express handlebars ecosystems seems very dormant these days to me. The root of the problem is that you want to pass the same template file (.hbs
) as a plain text file and as an interpreted template.
The solution I came up with doesn't involve escaping. There probably are ways to write a helper that escapes the template, but my remendation is use to Node's fs
to read the file on the system and store that as a local variable and pass it into the app render function.
Within external file:
var fs = require('fs');
var codeDir = './src/jquery/';
var exampleCode = {
badge: {
siteExample: fs.readFileSync(codeDir + 'badge/examples/site-example.js', 'utf8')
}
};
module.exports = exampleCode;
Within app.js
:
// Render code example pages
app.get('/jquery', function (req, res) {
var locals = {};
res.render('jquery/', locals, function () {
locals.code = codeExampleScripts;
res.render('jquery/index', locals);
});
});
This can be done with a custom block helper:
// [this is in /lib/hbs-helpers.js file]
exports.escapedPartial = function (partials, partialName, data) {
return partials[partialName](data.hash);
};
Registered with express-handlebars:
// [this is in js file which starts the express app, probably app.js]
var expressHandlebars = require( 'express-handlebars' );
var handlebarsHelpers = require('./lib/hbs-helpers');
var hbs = expressHandlebars.create({
defaultLayout: 'master',
extname: ".hbs",
helpers: handlebarsHelpers,
partialsDir: "views/partials"
});
// Configuring view engine
app.engine('.hbs', hbs.engine);
app.set('view engine', '.hbs');
And finally used from within the handlebars template itself (in some hbs file like, button-docs.hbs
). @exphbs.partials
must be passed through so that the helper has access to the partials (there is probably another better way for it to access this global, but, I don't know it):
{{> examples/buttons foo="bar"}}
<code>
{{escapedPartial @exphbs.partials "examples/buttons" foo="bar"}}
</code>
Compare "stash" {{
vs. "triple-stash" {{{
Handlebars HTML-escapes values returned by a
{{expression}}
. If you don't want Handlebars to escape a value, use the "triple-stash",{{{
.
http://handlebarsjs./#html-escaping