Is there an easy way how to pass a "configuration" parameter to all embedded partials in handlebars? In my case, I would like to set language by the page layout partial and would like all the embedded partials to have access to it, something like this:
@layout-en.hbs
:
SOMEHOW SETTING LANG PARAMETER TO "EN"
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{title}}</title>
</head>
<body>
<p>Top of all English pages</p>
{{{content}}}
<p>Footer of all English pages</p>
</body>
</html>
@layout-fr.hbs
- analogous
some-page-en.hbs
:
{{#> @layout_en title="Title in English"}}
some content in English
{{#> demo}}
some more content in English
{{/@layout_en}}
some-page-fr.hbs
:
{{#> @layout_fr title="Title in French"}}
some content in French
{{#> demo}}
some more content in French
{{/@layout_fr}}
Is it possible for demo
to return a button with a different text when included on a page using layout_en
and different when on a page using layout_fr
?
Or should this be done completely differently?
It's possible to set a variable that is accessible to all views and partials that are rendered in the response. I am doubtful that such a variable could be set from a partial and, even if it could, I would recommend against it because I think it would make the application more difficult to troubleshoot if global variables were being set in views.
Instead, I think a better approach would be to set such a variable in your controller logic.
You have not mentioned what Node web server framework you are using, but I am going to assume you are using express with the express-handlebars package.
The express API provides a locals object on the response (res
), to which variables can be attached and made available to all rendered templates.
A simple example of setting a global lang
variable within our express handlers looks like:
app.get("/en", (req, res) => {
res.locals.lang = "en";
res.render("some-page-en");
});
app.get("/fr", (req, res) => {
res.locals.lang = "fr";
res.render("some-page-fr");
});
This will allow us to use {{lang}}
from within any rendered view/layout/partial and the corresponding value will be rendered.
The problem with this approach is that it does allow for simple conditions within our template of the sort lang === "fr" ? "French content" : "English content"
. This is because Handlebars does not ship with a way to perform such a conditional check. A custom helper could help, however, if your application will only support the two languages - English and French - then we could replace our lang
string variable with a boolean one - ex., isFrench
:
app.get("/en", (req, res) => {
res.locals.isFrench = false;
res.render("some-page-en");
});
app.get("/fr", (req, res) => {
res.locals.isFrench = true;
res.render("some-page-fr");
});
As a boolean, this variable can be used with a Handlebars #if
helper. The demo
partial could then look something like:
<button type="button">
{{#if isFrench}}
Cliquez ici
{{else}}
Click here
{{/if}}
</button>
Additionally, I would recommend using a similar pattern within a single layout file instead of potentially having an English and a French layout with mostly duplicated HTML.
Additional note:
{{#> demo}}
on its own is not valid Handlebars syntax. The #>
is for rendering Partial Blocks and those must have an accompanying closing tag: {{/demo}}
. A regular (non-Block) partial would be rendered with {{> demo}}
.