Handlebars with Express: different html head for different pages

混江龙づ霸主 提交于 2019-11-29 20:11:08

This is a great question and, in my mind, a glaring weakness in Express's view model. Fortunately, there is a solution: use Handlebars block helpers. Here's the helper I use for this purpose:

helpers: {
    section: function(name, options){
        if(!this._sections) this._sections = {};
        this._sections[name] = options.fn(this);
        return null;
    }
}

Then, in your layout, you can do the following:

<head>
    {{{_sections.head}}}
</head>
<body>
    {{{body}}}
</body>

And in your view:

{{#section 'head'}}
    <!-- stuff that goes in head...example: -->
    <meta name="robots" content="noindex">
{{/section}}

<h1>Body Blah Blah</h1>
<p>This goes in page body.</p>

You can make the follow:

layout.hbs

<head>
    <title>{{title}}</title>
    {{#each css}}
        <link rel="stylesheet" href="/css/{{this}}" />
    {{/each}}
</head>

app.js

router.get('/', function (req, res, next) {
    res.render('index', { title: 'MyApp', css: ['style.css', 'custom.css'] });
});

Result:

<head>
    <title>MyApp</title>
    <link rel="stylesheet" href="/css/style.css" />
    <link rel="stylesheet" href="/css/custom.css" />
</head>

Maybe, you could use this implementation of the section helper: https://github.com/cyberxander90/express-handlebars-sections

You just need to install it and enable it:

yarn add express-handlebars-sections # or npm

const expressHandlebarsSections = require('express-handlebars-sections');

app.engine('handlebars', expressHandlebars({
    section: expressHandlebarsSections()
}));

Hope it helps.

Younes

I know this is an older question but I wanted to point out a clear alternative solution to what you are asking (I'm not entirely sure why nobody else spoke about it over the years). You actually had the answer you were looking for when you bring up placing things in {{{head}}} like you do for {{{body}}}, but I guess you needed help understanding how to make it work.

It seems possible that most of the answers on this page are geared towards Node "Sections" because you speak about the different sections of HTML you've included in your layout file that you want to change. The "Sections" everyone is speaking about in this thread seems to be a technique, although I may be mistaken, originating from Microsoft's Razor Template Engine. More info: https://mobile.codeguru.com/columns/dotnet/using-sections-and-partials-to-manage-razor-views.htm

Anyway Sections work for your question, and so could "Partials" theoretically (although it may not actually be the best option for this). More info on Partials: https://www.npmjs.com/package/express-partial

However, you simply asked for a way to alter the HTML tag content of your template layout in Handlebars, and assuming we are talking about HTML head tags, all you need to do is replace the content you have in your template layout HTML head tags with one of these (I use 3 brackets because it seems HTML would be included and you don't want it escaped):

<head> 
{{{headContent}}}
</head>

Then you just dynamically pass whatever data you want through the route you create in your app.js file to "get" the page like so (I am mostly taking the code @Fabricio already provided so I didn't have to rewrite this):

router.get('/', function (req, res) {
res.render( 'index', { headContent:'I DID IT!' });
});

Now when you load your page, "I DID IT!" will be where you expect it to show up.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!