Express hbs does not work - node.js

I know this post is a kinda dupplicate,
but I can't find out where I'm wrong.
/// my app.js //
var express = require('express'),
app = express();
app.use(express.static('public'));
app.use(express.static('views'));
//
app.engine('html', require('hbs').__express);
app.set('views', 'views');
app.set('view engine', 'html');
app.get('/', function(req, res) {
// res.sendFile(path.join(__dirname + '/index.html'));
//res.sendFile('/index.html');
res.render('index',{title :"page index"});
});
app.listen(3000);
Here my ./views/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body>
<h1>{{title}}</h1>
</body>
</html>
Any help ? thanks !

You should use .hbs as the extension.
Try to rename your /views/index.html to /views/index.hbs
and change it in the code as follows
app.set('view engine', 'hbs');
Apparently hbs wants .hbs to be used.
Tip: hbs hbs does not look so good to me, you can take a look at swig: http://paularmstrong.github.io/swig/docs

Try the below code
app.set('view engine', 'html');
app.engine('html', require('hbs').__express);
Instead of the this
app.engine('html', require('hbs').__express);
app.set('views', 'views');
app.set('view engine', 'html');

Related

express-handlebars isn't finding my layouts or partials

I have the following Express 4 view engine setup:
var handlebars = require('express-handlebars').create({
layoutsDir: path.join(__dirname, "views/layouts"),
partialsDir: path.join(__dirname, "views/partials"),
defaultLayout: 'layout',
extname: 'hbs'
});
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, "views"));
I have the following file structure:
/views
error.hbs
index.hbs
/partials
menu.hbs
/layouts
layout.hbs
And finally in my route: res.render('index');
And visiting my site, it loads only my index.hbs template. It does not use my layout.hbs. I don't get any errors or anything. It just doesn't use the layout even though layout is set as my default layout in the handlebars config.
Next I tried to change my code to this:
res.render('index', {layout: 'layout'});
Now I get the error:
Error: ENOENT: no such file or directory, open '/.../views/layout.hbs'
So it's like it's not finding my layoutsDir... What am I missing here?
Next I changed it to this:
res.render('index', {layout: 'layouts/layout'});
Okay so that worked. My layout is now loaded. But then I added in a partial to my layout:
{{> menu }}
Now I get: /.../views/index.hbs: The partial menu could not be found
So what is going on here? How come Handlebars isn't recognizing my layoutsDir or partialsDir? It's just not seeing them at all or something. And how come defaultLayout wasn't being used? I had to specify the layout.
According to the API documentation for express-handlebars if you are changing the file extension from the default .handlebars then when you set the view engine, all occurrences of handlebars should be replaced with the new extension you wish to use.
So your express setup will need to be updated to:
app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, "views"));
Note: the documentation uses a period before the extension e.g. .hbs but it seems to work without this.
Full code:
var path = require('path');
var express = require('express');
var app = express();
var http = require('http').Server(app);
var handlebars = require('express-handlebars').create({
layoutsDir: path.join(__dirname, "views/layouts"),
partialsDir: path.join(__dirname, "views/partials"),
defaultLayout: 'layout',
extname: 'hbs'
});
app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, "views"));
app.get('/', function(req, res){
res.render('index');
});
http.listen(3000, function(){
console.log("Server running");
});
In the new handlebars in your use partials you dont have to include its directory in server.js
The partials are included in "express-handlebars"
The first line in view engine setup is responsible for the above
Take note of these.
const hbs = require('hbs');
const expressHbs = require('express-handlebars');
//view engine setup
app.engine('.hbs', expressHbs({ defaultLayout: 'layout', extname: '.hbs' }));
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, '../views'));
app.use(express.static(path.join(__dirname, '../public')));
Try to use wildcard on your Dependencies to make sure you match the latest version
"dependencies": {
"express": "*",
"express-handlebars": "^3.0.0",
"hbs": "*"
},

Express js set view template options

In Express.js application to register template engine ejs you just add one line
app.set('view engine', 'ejs');
How to specify additional options supported by the ejs https://github.com/mde/ejs#options (e.g. I want rmWhitespace: true) so that every res.render() would use them?
UPDATE:
current set up:
...
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.locals.rmWhitespace = true;
app.get('/', function (req, res) {
res.render('root', { name: 'Test' });
});
and in `./views/root.ejs'
<html>
<body>
Hello, <%= name -%>
<br/>
</body>
</html>
Your original syntax works now:
app.set('view engine', 'ejs');
app.locals.rmWhitespace = true;
It didn't work at the time you asked your question, due to a bug which was fixed in v2.3.4: https://github.com/mde/ejs/commit/ea0fa32e27a13b9b77970b312699ff117aa56e59
Without this fix in place, rmWhitespace was not recognized as an "option", and therefore wasn't yanked out of data and into opts by the cbOptsInData method.
From documentation: ejs.render(str, data, options);
app.get('/', function (req, res) {
res.render('root', { name: 'Test' }, rmWhitespace);
});
http://ejs.co/
I had the same problem using swig, an alternative to ejs.
I think you can directly require ejs and set its options. For example :
var ejs = require('ejs');
...
app.set('view engine', 'ejs');
ejs.rmWhitespace = true;
...
You can setup a middleware
app.use(function(req, res, next){
res.locals.rmWhitespace = true;
next();
});
setup locals as res.locals
set docs here here

How can I use Express and EJS to serve static and dynamic content?

I want to build a simple app using node.js that 'functions' like IIS/classic ASP where all the content (html, png, js, css, ejs) can be in one directory and the ejs file uses javascript vs. VBScript.
I've gathered the following from API's and other examples, but the ejs file arrives at the browser as a binary and gets saved....
My node.js file:
var express = require('express');
var app = express();
app.use(app.router);
app.use(express.static(__dirname + '/html'));
app.engine('.ejs', require('ejs').__express);
app.set('views', __dirname + '/html');
app.set('view engine', 'ejs');
app.get('*.ejs', function(req, res) {
res.render(__dirname + '/html' + req.url, function(err, result) {
res.end(result);
});
});
app.listen(8080);
My test.ejs file:
<!DOCTYPE html>
<html>
<head><title>A test</title></head>
<body>
My Test Page
<% if (1==1) { %>
Working
<%}%>
</body>
</html>​
What am I missing or where can I find a working example?
I FIGURED IT OUT... SOLUTION ADDED ABOVE
express.js won't magically try to render static files, you have to explicitly call render somewhere.
I believe something like this would work:
var express = require('express')
var app = express()
app.engine('.ejs', require('ejs').__express)
app.set('views', __dirname + '/html')
app.set('view engine', 'ejs')
app.use(app.router) // only in express 3, remove that in express 4
app.get('/test.html', function(req, res, next) {
res.render('test.ejs')
})
app.use(express.static(__dirname + '/html'))
app.listen(8080)
I believe is not necessary to run render in every place, I use this example to render my static content by migrating express 2.3.7 to 4 and works fine with :
app.engine('.ejs', require('ejs').__express);
app.set('views', __dirname + '/public')
app.set('view engine', 'ejs')
app.use(express.static(__dirname + '/public'))
My static content is in 'public' directory.
I just want to add that express supports EJS out of the box these days:
https://expressjs.com/en/starter/generator.html

Change .ejs extension to .html using Parse.com Express.js

How would I go about using .html extensions on my view files instead of .ejs when using Parse.com's Express.js?
I changed the EJS delimiters to <? and ?> because I'm used to them from PHP. That worked fine, but I can't seem to change the file extension for my view files:
I've tried the following:
var express = require('express');
var ejs = require('ejs');
var app = express();
ejs.open = '<?';
ejs.close = '?>';
app.set('view engine', 'ejs');
app.engine('.html', ejs.renderFile);
app.set('views', 'cloud/views'); app.use(express.bodyParser());
app.get('/', function(req, res) {
res.render('Test', { message: 'Hello Express!' });
});
app.listen();
And I get an internal server error.
I've also tried eliminating this line with the same result:
app.set('view engine', 'ejs');
app.set('view engine', 'html');
app.engine('html', ejs.renderFile);
So I did app.set to html and app.engine to html and it was working for me.
this way works too:
app.set('view engine', 'html');
app.engine('html',require('ejs').renderFile);
someone knows any problem using this way?

layout.ejs not rendered - Node.js, Express

I am trying to execute a simple example of node.js with EJS templates. Node, or rather express is unable to render the index page, as in the following code, with layout.ejs, no matter what I do.
Here's the app.js
var express = require('express')
, routes = require('./routes')
, http = require('http');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 8001);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.set('view options', {layout: 'views/layout.ejs'});
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
layout.ejs
<!DOCTYPE html>
<html>
<head> <title><%= title %></title> </head>
<body> <%- body %> </body>
</html>
And in index.ejs, it's just this
<p> Some Text </p>
Have I missed something here?
app.set('view options', { layout:'layout.ejs' });
remove the views/ and it should work.

Resources