how to get handlebar-layouts working in node/hapi.

2019-05-10 08:04发布

问题:

I'm having trouble getting handlebars-layouts to render in a hapi.js app. The layout renders fine but the partial doesn't render at all and just has a blank.

I'm declaring it like this:

var handlebars = require('handlebars'),
  layouts = require('handlebars-layouts');
layouts(handlebars);

server.views({
  engines: {
    html: handlebars
  },
  basePath: __dirname,
  path: './views',
  layoutPath: './views/layout',
  partialsPath: './views/partials',
  layout: true,
  helpersPath: './views/helpers'
});

and the boiler plate layout

<html>
  <body>
    {{#content "body"}}
        <h2>Welcome Home</h2>
    {{/content}}

    {{#content "foot"}}

    {{/content}}
 </body>
</html>

and html partial

{{#extend "layout"}}

    {{#content "body"}}
        <h2>Sub page content</h2>
    {{/content}}

    {{#content "foot" mode="prepend"}}
        <script src="assets/js/analytics.js"></script>
    {{/content}}
{{/extend}}

回答1:

Hapi supports layouts out of the box. The problem is that you are trying to use hapi's layout support together with the handlebars-layouts module. It's not going to work. Either use the built-in layout support, or use handlebars-layouts. Also, in the layout you need to use {{#block "body"}}{{/block}} instead of {{#content "body"}}. Here are two examples:

With the handlebars-layouts module:

index.js:

var Handlebars = require('handlebars');
var HandlebarsLayouts = require('handlebars-layouts');
var Hapi = require('hapi');
var Path = require('path');

var engine = Handlebars.create();
HandlebarsLayouts.register(engine);

var server = new Hapi.Server();
server.connection({
    host: '127.0.0.1',
    port: 8000
});

server.views({
    engines: {
        html: engine
    },
    path: Path.join(__dirname, 'views'),
    partialsPath: Path.join(__dirname, 'views/partials)'
});

server.route({
    method: 'GET',
    path: '/item',
    handler: function (request, reply) {

        reply.view('item', { title: 'Item Title', body: 'Item Body' });
    }
});

server.start();

views/partials/page.html:

{{#extend "layout"}}

    {{#content "body"}}
        <h2>{{title}}</h2>
    {{/content}}

    {{#content "foot" mode="prepend"}}
        <script src="assets/js/analytics.js"></script>
    {{/content}}

{{/extend}}

views/partials/layout.html:

<html>
  <body>
    {{#block "body"}}
        <h2>Welcome Home</h2>
    {{/block}}

    {{#block "foot"}}

    {{/block}}
 </body>
</html>

views/item.html:

{{#embed "page"}}{{/embed}}

{{body}}

With hapi's built-in layout support:

index.js:

var Handlebars = require('handlebars');
var Hapi = require('hapi');
var Path = require('path');

var server = new Hapi.Server();
server.connection({
    host: '127.0.0.1',
    port: 8000
});

server.views({
    engines: {
        html: Handlebars.create()
    },
    path: Path.join(__dirname, 'views'),
    layoutPath: Path.join(__dirname, 'views/layout'),
    layout: true,
    partialsPath: Path.join(__dirname, 'views/partials')
});

server.route({
    method: 'GET',
    path: '/item',
    handler: function (request, reply) {

        reply.view('item', { title: 'Item Title', body: 'Item Body' });
    }
});

server.start();

views/layout/layout.html:

<html>
  <body>
    {{> header}}

    {{{content}}}

    {{> footer}}
 </body>
</html>

view/partials/footer.html:

<script src="assets/js/analytics.js"></script>

views/partials/header.html:

<h2>{{@root.title}}{{^title}}Welcome Home{{/title}}</h2>

views/item.html:

{{body}}