Passing user detail to jade with everyauth and express - node.js

I have started a small webapp with everyauth and express, based on the sample project in Mircosoft's WebMatrix 2.
What I cannot get my head around is how information is passed to the view and how the views are stiched together from partial views.
The view is generated from a parent view called layout.jade and the partial view for example index.jade. These views do however not seem to reference each other.
The routing seems to be managed with this code:
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('./middleware/locals'));
app.use(express.cookieParser());
app.use(express.session({ secret: '[secret]' }));
app.use(everyauth.middleware());
app.use(express.compiler({ src: __dirname + '/public', enable: ['less'] }));
app.use(connect.static(__dirname + '/public'));
app.use(app.router);
});
and the routes are defined like this:
app.get('/', function(req, res) {
res.render('index', { title: 'Home Page. ' })
});
This seems to perfectly merge the layout and partial view, but I cannot work out how. Can anyone shed light how this works?

If you are not coming from a ruby background it can be kind of hard to grasp, hopefully this helps.
By default express will render a "layout" (in your case layout.jade). A layout is then rendered on every page unless specified else where. Although this maybe helpful with websites and blogs where the head is always the same, I find it to be cumbersome on web applications. You can disable if you like by adding the code below to your app settings:
app.set('view options', {layout: false});
Express will then render your view (in this case index.jade). The index is the majority of the content.
Express can also render partials, which is a partial view inside of a view. This is helpful for items like footers, but can effect performance. It is important to note that a partial is different then a view.
I find that people without Jade/Tempting experience have an smaller learning curve using EJS instead of Jade, since it flows much like HTML.
Below are some videos that really helped me grasp views/partials, and middleware when I first started with express. Nodetuts is an excellent resource. The Express documentation has also evolved to be a very valuable resource as well, happy coding, and good luck!
express documentation
nodetuts express

Related

Express NodeJS Cannot find module 'html'

I have a Node Server with Express. I get the cannot find module 'html' error even though my code looks like this and should be correct in my opinion:
app.set('views', path.join(__dirname, 'build/views'));
app.use(favicon(path.join(__dirname, "build/favicon.ico")));
app.use('/scripts', express.static(path.join(__dirname, 'node_modules')));
app.use(express.static(path.join(__dirname, 'build')));
app.get('/', function(req, res){
res.render('index.html');
});
You have to set engine for HTML
Include this code in your main file
var engines = require('consolidate');
app.engine('html', engines.mustache);
app.set('view engine', 'html');
If you only want to serve a static file without passing any variables from the server to the client the easiest solution would be:
res.sendFile(path.join(__dirname + '/build/views/index.html'));
Especially when you are using AngularJS for the client side. The problem with the solution above is that mustache uses {{}} as variables recognition. So does AngularJS which might causes errors!
It seems that you are trying to display a static index.html file but you serve it as if it was a template. Probably Express is trying to find a module for html template format, which doesn't exist.
You may try to send the index as a static file instead of with res.render which is for rendering templates.
Some time ago I wrote an example of serving static files with Express. It's available on GitHub:
https://github.com/rsp/node-express-static-example
See also my other answer, where I explain it in more detail.

Expressjs order of app.router and express.static

To configure my Expressjs app I have these two lines (amongst others):
...
app.use(express.static(__dirname + '/public'));
app.use(app.router);
...
I've read that the recommendation is to put the router before static but when I do my Angularjs app renders a blank page. When they are in the order shown the views render normally.
Why is this?
It is the best to explain with an example. Let's say, you have an en.json file and you also have a route:
app.get('/en.json', function(req, res) {
res.send('some json');
});
If you put
app.use(app.router);
before
app.use(express.static(__dirname + '/public'));
router will have a priority over static file, and user will see some json, otherwise en.json file will be served.
So if you don't have such collisions it doesn't matter which order you choose.
P.S. Note that if you're using Express 4 you may see this error:
Error: 'app.router' is deprecated!
Please see the 3.x to 4.x migration guide for details on how to update your app.
On the wiki page #HectorCorrea has shared in comments there is an explanation of this error:
no more app.use(app.router)
All routing methods will be added in the order in which they appear
Hope this helps

How to use .html file extensions for handlebars in express?

So I was wondering how I could use .html extensions instead of .handlebars or .hbs extensions. I am doing this so I can develop using regular html so that my frontend developers can seamless edit files in their IDEs without any extra configuration. Plus it will help installing html templates much faster into our express applications.
So I was able to do this by changing three things in my app.js file I hope this helps everyone out as much as it helped me!
var express = require('express'),
exphbr = require('express3-handlebars'), // "express3-handlebars"
helpers = require('./lib/helpers'),
app = express(),
handlebars;
// Create `ExpressHandlebars` instance with a default layout.
handlebars = exphbr.create({
defaultLayout: 'main',
helpers : helpers,
extname : '.html', //set extension to .html so handlebars knows what to look for
// Uses multiple partials dirs, templates in "shared/templates/" are shared
// with the client-side of the app (see below).
partialsDir: [
'views/shared/',
'views/partials/'
]
});
// Register `hbs` as our view engine using its bound `engine()` function.
// Set html in app.engine and app.set so express knows what extension to look for.
app.engine('html', handlebars.engine);
app.set('view engine', 'html');
// Seperate route.js file
require("./routes")(app, express);
app.listen(3000);
Agree with JemiloII,
extname: '.myext' in the config while creating the expr-HBS instance (exphbr.create()) according to https://www.npmjs.org/package/express3-handlebars#-extname-handlebars-
binding the expr-HBS engine to the extension: app.engine('myext', handlebars.engine); according to http://expressjs.com/3x/api.html#app.engine
set the extension as view engine: app.set('view engine', 'myext'); - unfortunately no link to how it works.
Regards

Is there any way to use multiple view engines with Express + Node.js

Scenario: I had developed some transactional pages using Node.js, Express + Handlebars as view engine and MongoDB.
Now the issue is during module integration I got some of the pages which are built on Express + Jade as view engine.
Question: How to integrate pages built on Handlebars & some on Jade?
Add both engines and consolidate.js in your package.json
In yourapp.js
var engines = require('consolidate');
app.engine('jade', engines.jade);
app.engine('handlebars', engines.handlebars);
More info here
Express 4.0 and up solution (until it changes again)
NPM install the engines you need.
// some examples
npm install ejs
npm install pug
npm install handlebars
Set the engines to use in your app.js.
app.set('view engine', 'pug');
app.set('view engine', 'ejs');
Render your template, be sure to set the file extension.
// forces usage of the respective render engine by setting the file extension explicitly.
res.render( 'about.ejs', { title: 'About' } );
res.render( 'about.pug', { title: 'About' } );
Documentation for more usage examples.
https://expressjs.com/en/guide/using-template-engines.html
EDIT
After discussing with Amol M Kulkarni below comments, I came back and analyzed these again.
And turns out, it was fairly easier than I thought that I have to get back here and share my solution. Using consolidate, do it like this:
First do the require.
var engines = require('consolidate');
Then you can either remove or set engine and view engine...
I have tried removing all app.engine and app.set('view engine', '...'); and it did work. However, setting it other than 'html' will only work for one engine. So I just have set it to be sure.
I have set it like so:
app.engine('html', engines.swig); // take note, using 'html', not 'ejs' or 'pug'..
app.set('view engine', 'html'); // also 'html' here.
And then later on when you do the app.render, just make sure it has the file extension and it will just work nicely.
res.render( 'theme.ejs', {}); // will render with ejs
res.render( 'theme.pug', {}); // will render with pug
Just make sure have these engines (pug, ejs, etc..) are installed and consolidate will do the rest.
Old answer.
with relation to #Sergii answer, it did not work for me 100%.
There are times when an error is raised in the templates I'm using. But with a wrong error message that says failed to look up this template in this directory.
I tried #azariah solution but still did not work.
app.set('view engine', 'pug'); // does not make sense.
app.set('view engine', 'ejs'); // overriding the last .set()
what worked for me is using consolodate.js as mentioned.
Added app.set('view engine', 'pug'); as usual.
And then, in every time I will call render, I set the 'view engine'.
like so:
req.app.set('view engine', 'ejs');
res.render( 'theme', theme );
My worries with this is that when more simultaneous users will visit page with different engines, not sure if this will collide and be back with the error look up that I'm having.
But I guess that the render is so fast, that it should be done by the time another req.app.set is called.
I found this as more accurate and this is my personal practice.
We should have a default template engine set, so that all all views should process through at-least one template engine, it will save the file from being exposed to end user, in case you have html as default engine.
therefore, start with installing consolidate.js to the directory.
npm install consolidate
Later, we need to add the installed module to the application file.
var consoengines = require('consolidate');
Now setting the default view engine, (choosing pug because of its popularity)
app.set('view engine', 'pug');
After setting the default template engine. now I need to install the additional template engine, for my case, I mostly need EJS, because it allows almost all Javascript, which comes handy, to make anything in template. but you are good to choose any template engine.
All you would have to do is, install your template engine
npm install ejs
Now add this to consolidate instance and then put back to main template engines list.
app.engine('ejs', engines.ejs);
Now each time, you render a template, if you don't give extension in your router, this will call it with the default set template engine (here it is PUG), otherwise it will call the template engine according to the extension mentioned in the router call.

static javascript not rendering in jade (with express/node.js)

I hope you are well.
I'm suddenly unable to render any external javascript in jade templates! To get to the bottom of things, I stripped it down to the bare minimum :
Node 0.6.11, Express 2.5.8, jade 0.20.3
app.js
var express = require('express')
, routes = require('./routes');
var app = module.exports = express.createServer();
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
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({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
app.get('/', function(req, res){
res.render('index', { title: 'Express' });
});
app.listen(3000);
layout.jade
!!!
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
script(type='text/javascript', src='/javascripts/script.js')
body!= body
script.js
alert('hello!');
It seems to me that when I run the server and load http://localhost:3000/, I should straightaway get a 'hello!' message, but it just runs straight to the normal page.
What's more, if I manually type
script
alert('hello!')
into the layout.jade template I get the message just as I should. It is just not loading the static script. And I have certainly checked that 'script.js' is in '/public/javascripts/' just as it should be.
Any advice would be very welcome!!!
Thanks in advance
you need to pass your script from the controller like that:
app.get('/', function(req, res){
res.render('index', { title: 'Express', scripts: ['javascripts/script.js']});
});
and then in your head in layout.jade:
- each s in scripts
script(src=s)
Make sure your js files are exposed as static resources.
In layout.jade...
!!!5
html
head
script(src='js/helper.js')
In app.js...
app.use(express.static(__dirname + '/public'));
Once I put the 'js' folder under the 'public' folder, helper.js loaded without issue. Simple, but I'm new to this whole thing and I didn't get that at first.
Why do you have a beginning forward slash '/' in your Jade script tag? With your script in <root_dir>/public/javascripts/script.js, the correct way to reference it in Jade is script(src="javascripts/script.js"). At least that is what is working on my installation. The same is true for other assets like CSS or images in the /public directory.
Thanks to Rob (you can find his answer above), for pointing in right direction. I just want to add a little reference so it might seem more natural than any magic.
In the express documentation here, its mentioned that if static files like css, images etc are to be served then one need to declare it using
app.use(express.static("_dirName"));
I was facing same issue with using images in html code. With this, it works fine now.

Resources