How to change default layout in express using handlebars?
I am using Express 4.9.0 and express-generator.
Created boilerplate with a following command:
express --hbs projectname
Builtin handlebars is using views/layout.hbs
by default as a master page. But i cannot see any settings in my app.js to change that behaviour.
piece of code from my app.js:
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
- How can i change my default layout globally?
- What if i want to have 2 or 3 different global layouts?
Solution 1:
You can specify what layout you want to use as part of the render call. If you create a new layout called other.hbs
, you can then do something like:
res.render('view', { title: 'my other page', layout: 'other' });
To override this for the entire application, you can use:
app.set('view options', { layout: 'other' });
Solution 2:
From the handlebars readme:
There are two ways to set a default layout: configuring the view engine's defaultLayout property, or setting Express locals app.locals.layout.
The layout into which a view should be rendered can be overridden per-request by assigning a different value to the layout request local. The following will render the "home" view with no layout:
app.get('/', function (req, res, next) { res.render('home', {layout: false}); });
In case you want to set the default layout just for a specific subroute, you might wanna use the following in the top section of your route:
router.all('/*', function (req, res, next) {
req.app.locals.layout = 'admin'; // set your layout here
next(); // pass control to the next handler
});
You can also set the default layout on initialization:
// Create `ExpressHandlebars` instance with a default layout.
var hbs = exphbs.create({
defaultLayout: 'main',
helpers : helpers,
// Uses multiple partials dirs, templates in "shared/templates/" are shared
// with the client-side of the app (see below).
partialsDir: [
'shared/templates/',
'views/partials/'
]
});
// Register `hbs` as our view engine using its bound `engine()` function.
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
Solution 3:
This should work now..
npm install express-handlebars
.
├── app.js
└── views
├── home.handlebars
└── layouts
└── main.handlebars
2 directories, 3 files
app.js
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.get('/', function (req, res) {
res.render('home');
});
app.listen(3000);
views/layouts/main.handlebars:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Example App</title>
</head>
<body>
{{{body}}}
</body>
</html>
Solution 4:
I hope you are using express-handlebars
. This instructions are for express-handlebars. For hbs
, procedures are little different.
Step-1: Require handlebars
const exphbs = require('express-handlebars');
step-2: Register handlebars template engine. while registering, you can configure
for changing layout directory
const layoutPath = path.join(__dirname, './templates/layouts'); //you can build your desired path
app.engine('handlebars', exphbs({ layoutsDir: layoutPath }));
other available options along with layoutsDir are
interface ExphbsOptions {
handlebars?: any;
extname?: string;
layoutsDir?: string;
partialsDir?: any;
defaultLayout?: string;
helpers?: any;
compilerOptions?: any;
}
step-3: If you want to change views directory
const viewPath = path.join(__dirname, './templates/views');
app.set('views', viewPath);
step-4: For some template, If you don't wish to give layout, you have to specify as layout: false
. Otherwise app will crash. You can configure as follow, if you need.
app.get('/', (req, res, next) => {
res.render('shop', { title: 'My Shop', layout: false })
});
For more info about express-handlebars