Displaying views in Node.js/Express - node.js

I am following the peepcode (part 1) video tutorial on node.js, and I am getting stuck on the first few steps. When I try to go to http://localhost:3000/login, I get the following error:
500 Error: Failed to lookup view "/Users/dantang/Desktop/Programming/Node/basic server/hotpie/apps/authentication/views/login"
I'm guessing it is due to a typo, but I've tried changing the code several times and I can't figure out what is wrong. Would really appreciate it if someone could tell me what should I do? Thank you!
The github repo is https://github.com/tangbj/nodejs
Server.js
/**
* Module dependencies.
*/
require("coffee-script");
var express = require('express')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
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(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
//Routes
require('./apps/authentication/routes')(app);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
login.jade
form(action='/sessions', method='post')
label
| Username
input(type='text', name='user')
label
| Password
input(type='password', name='password')
input(type='submit', name='Submit')
routes.coffee
routes = (app) ->
app.get '/login', (req, res) ->
res.render "#{__dirname}/views/login",
title: 'Login'
stylesheet: 'login'
module.exports = routes
package.json
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "3.1.0",
"jade": "*",
"coffee-script": "~1.6.1"
}
}

There was something wrong with your login.jade file. Maybe some encoding problem. I created a newLogin.jade file, changed the render function and everything works fine. See the pull request at github.

It will be unable to find the path if you are using Windows which requires backslash instead of forward-slash in linux. So use path.join or path.normalize to get correct paths.
Try to change this in your routes.coffee
res.render "#{__dirname}/views/login",
to
res.render path.join(__dirname, "/views/login"),
and
app.set('views', __dirname + '/views');
to
app.set('views', path.join(__dirname + '../views'));
Otherwise verify the location of the directories/files.

Related

dustjs-linkedin with express 3

I am trying to get dustjs-linkedin working with an express 3 project, however I can't seem to get past this error:
Error: Template name parameter cannot be undefined when calling dust.compile
at Object.compiler.compile (/home/user/project/node_modules/dustjs-linkedin/lib/compiler.js:21:16)
at Object.dust.compileFn (/home/user/project/node_modules/dustjs-linkedin/lib/dust.js:109:37)
at Function.exports.dust.render (/home/user/project/node_modules/consolidate/lib/consolidate.js:226:56)
at /home/user/project/node_modules/consolidate/lib/consolidate.js:146:25
at /home/user/project/node_modules/consolidate/lib/consolidate.js:99:5
at fs.js:266:14
at Object.oncomplete (fs.js:107:15)
I can reproduce this with a brand new express 3 project like so:
app.js
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var app = express();
// added these 3
var dust = require('dustjs-linkedin');
var cons = require('consolidate');
app.engine('dust', cons.dust);
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
// added this 1
app.set('view engine', 'dust');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
package.js
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.4.7",
"dustjs-linkedin": "*",
"consolidate": "*"
}
}
routes/index.js
exports.index = function(req, res){
res.render('index', { title: 'Express' });
views/index.dust
Title: {title}
The strange thing is, I have a project using express 3 and dustjs-linkedin that is working just fine. I ran a diff on the files in the dustjs-linkedin module and the working version has a lot of files in dist while the project throwing the error only has a few, namely:
working/node_modules/dustjs-linkedin/dist:
dust-core.js dust-core.min.js dust-full.js dust-full.min.js LICENSE
workingProject/node_modules/dustjs-linkedin/dist:
dust-core-1.1.1.js dust-core-2.0.0.min.js dust-full-1.2.0.js dust-full-2.0.1.js
dust-core-1.2.0.js dust-core-2.0.1.js dust-full-1.2.1.js dust-full-2.0.2.js
dust-core-1.2.1.js dust-core-2.0.2.js dust-full-1.2.2.js dust-full-2.0.3.js
dust-core-1.2.2.js dust-core-2.0.3.js dust-full-1.2.2.min.js dust-full-2.1.0.js
dust-core-1.2.2.min.js dust-core-2.1.0.js dust-full-1.2.3.js dust-full-2.2.0.js
dust-core-1.2.3.js dust-core-2.2.0.js dust-full-1.2.3.min.js dust-full-2.2.2.js
dust-core-1.2.3.min.js dust-core-2.2.2.js dust-full-1.2.4.js dust-full-2.2.2.min.js
dust-core-1.2.4.js dust-core-2.2.2.min.js dust-full-1.2.5.js dust-full-2.2.3.js
dust-core-1.2.5.js dust-core-2.2.3.js dust-full-1.2.6.js dust-full-2.2.3.min.js
dust-core-1.2.6.js dust-core-2.2.3.min.js dust-full-2.0.0.js
dust-core-2.0.0.js dust-full-1.1.1.js dust-full-2.0.0.min.js
This demo of a 'working' project gives me the same error:
https://github.com/chovy/express-template-demo
[Edit]
An issue is discussed here:
https://github.com/linkedin/dustjs/commit/e5ebff0f7b32f8ff0883be7f7924507b314eef1d
In [/node_modules/]consolidate/lib/consolidate.js go to exports.dust.render function:
...
try {
var tmpl = cache(options) || cache(options, engine.compileFn(str));
tmpl(options, fn);
} catch (err) {
fn(err);
}
...
engine.compileFn is called sending str as parameter, str is actually the template itself:
Title: {title}
engine.compileFn is compiler.compile(source, name) in [/node_modules/]dustjs-linkedin/lib/compiler.js.
source is template sent, however name which is the template name and should be index in our case, is never set (undefined).
Alternatively, I prefer to use Payapl's Adaro library for express 3.x and linkedin-dustjs. It's part of their project kraken.js, but can be used as a standalone dust wrapper for express:
https://github.com/paypal/adaro
As mentioned in README.md:
var express = require('express');
var dustjs = require('adaro');
var app = express();
app.engine('dust', dustjs.dust({});
app.set('view engine', 'dust');
// For rendering precompiled templates:
// app.engine('js', dustjs.js({ ... ));
// app.set('view engine', 'js');

Send 404 header from not existent static content when using * route in Express

I'v got express app like this.
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
app.get('*', function(res,req) {
req.render('index', {title: "Title"});
});
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
Because of using app.get('*') request to not existent static files responses with rendered index.ejs file instead of error 404.
Is there any way to fix it without additional conditions in routes?
Just add something like:
app.get(/\/(js|css|img)\/.*/, function (req, res) {
res.send(404);
});
before app.get('*'). Any request to /js that wasn't already matched by the static middleware references an file that does not exist.
Resolved problem by nginx proxying

How to add my existing views,stylesheets,javascripts to express?

I have an existing coded frontend i.e views,javascripts,stylesheets (https://github.com/stdrunk/Taskr) and I intend to add this to the express framework so that i can link it to the db.
I added the contents to the public folder. The javascripts in the javascript folder, css in stylesheets, and images in images folder.
Then i changed the code of app.js according to this Render basic HTML view?
Now when run app.js and open the page in the browser i get a stripped version of my original page.
No error comes in the console.
This is my app.js
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
//app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.use(express.static(__dirname + '/public'));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
app.get('/home', function (req, res)
{
res.render('index.html');
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
You could put all those dirs under a 'public' dir, and then use:
app.use(express.static(__dirname + '/public'));
That way, express will always just send anything requested from those directories, and you won't need to worry about static files at all.
Although, I do recommend keeping something like Apache running on your server to serve static files. Images especially.

Nodejs cannot get /login

Hi i am following peepcode nodejs screencast, now i have an issues of rendering the login form. My code are as follow:
app.js
/**
* Module dependencies.
*/
require('coffee-script');
var express = require('express')
, http = require('http')
, path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
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(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
require('./apps/authentication/routes');
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
and my i have a routes within authentication folder. The code as follow:
routes.coffee
routes = (app) ->
app.get '/login', (req,res) ->
res.render "views/login",
title: 'Login'
stylesheet: 'login'
module.exports = routes
The coffee script indentation all works fine, but i have an error when i navigate localhost:3000/login on browser. The error it display are Cannot GET /login. Where am i wrong?
In app.js, change this line:
require('./apps/authentication/routes');
to this:
require('./apps/authentication/routes')(app);
What is happening is that in routes.coffee, you're exporting a function that takes a single arg, 'app', and then sets up the route on your app object. You need to call it passing app as the argument.

JSHTML not working on Express.js in Node.js

I don't seem to get JSHTML to work as a template engine on Express.js in Node.js. When I install my Express.js application and a basic application is created for me, and I run it I get this error message:
500 TypeError: Property 'engine' of object #<View> is not a function
at View.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/view.js:75:8)
at Function.app.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/application.js:504:10)
at ServerResponse.res.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/response.js:677:7)
at exports.index (/Users/blackbook/nodejs/ds/routes/index.js:7:7)
at callbacks (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:165:11)
at param (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:139:11)
at pass (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:146:5)
at Router._dispatch (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:173:5)
at Object.router (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:33:10)
at next (/Users/blackbook/nodejs/ds/node_modules/express/node_modules/connect/lib/proto.js:190:15)
My app.js looks like this (it's what Express.js created for me):
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
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(path.join(__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'));
});
I have this installation:
Node.js v.0.8.5
Express.js#3.0.0rc2
jshtml#0.2.3
JSHTML currently works with Express.js 2. There are plans on getting the engine to work with Express.js 3, but currently I am too busy with enjoying the summer! Expect a fix for this problem in the winter!
According to https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x you can use app.engine for 2-x compatibility.
e.g.
var fs = require("fs");
var jshtml = require("jshtml");
app.engine("jshtml", function (path, options, fn) {
fs.readFile(path, 'utf8', function (err, str) {
if (err) return fn(err);
str = jshtml.compile(str,options)(options).toString();
fn(null, str);
});
});
consolidate.js is used as a bridge between many template engines and express. If your engine isn't supported checkout the source code. Most engines need like 15 lines of code to implement.
I have it working in my project and will probably issue a pull request soon but for now look at my comment in
https://github.com/elmerbulthuis/jshtml/issues/5
Try the following. It works for me, as like you.
Firstly, install jshtml-express via npm and then do the following.
var app = express();
**app.engine('jshtml', require('jshtml-express'));**
// All environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
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(path.join(__dirname, 'public')));
I hope it will work for you as well.

Resources