My Node.js app is configured as such:
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
//etc.
});
My views folder only contains index.ejs and I don't want to use layouts now. However I am getting:
failed to locate view "layout", tried:
- /Users/stephane/code/node/project/views/layout.ejs
Why?
There is an option to specify that we don't want to use layouts within the view:
app.set('view options', {
layout: false
});
Related
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": "*"
},
How can I output pretty HTML using Swig in Express? I have tried the following:
app.set('view options', { pretty: true });
app.locals.pretty = true;
using Production environment
My view code looks like this:
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'swig');
app.engine('.swig', swig.renderFile);
Try with swig Filter. example: {{character|safe}}
you can get more here http://paularmstrong.github.io/swig/docs/filters/
I've got a pretty basic expressjs application with the / route loading a view located in views/main/. However, I'm getting the following error:
Error: Failed to lookup view "main/index" in views directory "/Users/n0pe/Sync/src/proj/views/"
Here's my structure (omitting the unimportant):
/proj
/views
/main
index.hbs
app.js
And here's my app.js (the important parts):
var express = require('express');
var app = express();
app.set('views', __dirname+'/views/');
app.set('view engine', 'handlebars');
And here's the controller:
router.get('/', function(req, res, next) {
res.render('main/index', {title: 'test'});
});
What's missing from this pretty basic setup?
I tested it in local and everything works. Just one mistake
from app.set('view engine', 'handlebars'); to app.set('view engine', 'hbs');
my example
var express = require('express'),
app = express();
app.engine('html', require('hbs').__express);
app.set('views', __dirname+'/views/');
app.set('view engine', 'hbs');
app.get('/', function(req, res) {
res.render('main/index',{title :"page index"});
});
app.listen(3000);
I changed two things and it worked for me.
First
app.set('views', [path.join(__dirname, 'views'),path.join(__dirname, 'views/main')]);
I passed an array to the app.set and added the subdirectory
Second
res.render('../main/index', {title :"page index"}, function(err, html) {
console.log(err);
});
I changed the directory path to relatively navigate from the parent directory.
Using the ../ makes it work somehow. Also, once you add the directory to the app.set, you can call index directly e.g., res.render('index',...
Change your set views. it should be
app.set('views', path.join(__dirname, 'views'));
I think you need to change the file extension of the views from hbs to handlebars
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?
I want to use 2 layouts for main page and admin page
What should i configure my code to do that?
here is my current code configure
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(express.static(__dirname + '/public'));
app.use(express.cookieParser());
app.use(express.session({secret: 'secrect', store: MemStore({
reapInterval: 60000 * 10
})}));
app.use(app.router);
});
I usually set layout to false globally, so I know exactly what layout I use where (so no default layout):
app.set('view options', { layout: false });
Then in my routes I can set a layout per route like so:
res.render('my_page', { layout: 'my_layout' });
Read more about Express layouts and templates engines