Menu Close

Server-Side Development with Hapi.js — Views

Hapi.js is a small Node framework for developing back end web apps.

In this article, we’ll look at how to create back end apps with Hapi.js.

Views

We can render templates in our Hapi app.

For example, we can write:

index.js

const Path = require('path');
const Hapi = require('@hapi/hapi');
const Hoek = require('@hapi/hoek');

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0',
    debug: { request: ['error'] }
  });
  await server.register(require('@hapi/vision'));
  server.views({
    engines: {
      html: require('handlebars')
    },
    relativeTo: __dirname,
    path: 'templates'
  });

  server.route({
    method: 'GET',
    path: '/',
    handler (request, h) {
      return h.view('index');
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};
process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

templates/index.html

<p>hello</p>

We register the Hapi Vision plugin to let us render views:

await server.register(require('@hapi/vision'));

Then we set the view options with:

server.views({
  engines: {
    html: require('handlebars')
  },
  relativeTo: __dirname,
  path: 'templates'
});

engines specify the view engine to use.

relativeTo sets the path that the templates are stored relative to.

path is the path to the templates.

We render the view with:

return h.view('index');

We specify the file name of the template to render it.

So when we to the / we see hello rendered.

Other paths we can specify include:

  • partialsPath: the folder that contains our partials
  • helpersPath: the folder that contains our template helpers
  • layoutPath: the folder that contains layout templates

So we can write:

const Path = require('path');
const Hapi = require('@hapi/hapi');
const Hoek = require('@hapi/hoek');

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0',
    debug: { request: ['error'] }
  });
  await server.register(require('@hapi/vision'));
  server.views({
    engines: {
      html: require('handlebars')
    },
    relativeTo: __dirname,
    path: 'templates',
    layoutPath: './templates/layout',
    helpersPath: './templates/helpers'
  });

  server.route({
    method: 'GET',
    path: '/',
    handler (request, h) {
      return h.view('index');
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};
process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

to specify the paths.

Global Context

We can pass in data by passing in the context object to the server.views call.

For example, we can write:

index.js

const Path = require('path');
const Hapi = require('@hapi/hapi');
const Hoek = require('@hapi/hoek');

const context = {
  title: 'My personal site'
};

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0',
    debug: { request: ['error'] }
  });
  await server.register(require('@hapi/vision'));
  server.views({
    engines: {
      html: {
        module: require('handlebars'),
        compileMode: 'sync'
      },
    },
    relativeTo: __dirname,
    path: 'templates',
    context
  });

  server.route({
    method: 'GET',
    path: '/',
    handler (request, h) {
      return h.view('index');
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};
process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

templates/index.html

<p>{{title}}</p>

We have the context object.

And we pass that into the object we call server.views as its property.

In templates/index.html , we render the title in the template.

So we see:

My personal site

displayed when we go to / .

Conclusion

We can render views with the Hapi Vision plugin.

Posted in Hapi