Where does express get the default value for its title variable. My index.jade looks like the following:
h1= title
p Welcome to #{title}
I don't quite understand where the title variable is set.
In your routes/index.js you will be saying
res.render('index', { title: 'Express' });
So here it will find views/index.jade put value of title variable as 'Express'.
You can say in your jade
p Welcome to #{title} from #{name}
and while renderring
res.render('index', { title: 'Express' ,name: 'myName'});
it will be converted in Welcome to Express from myName.
In express, the template (.jade for example) has access to
anything in app.locals which are basically global variables
anything in res.locals which are tied to the request/response cycle of the current request
anything passed to it via res.render() which will have typically been determined in your request route handler
Just to expand on this, here is an example that should demonstrate:
app.js:
var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var app = express();
//set a global variable that will be available to anything in app scope
app.locals.globalVar = "GLOBAL";
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.urlencoded());
app.use(express.methodOverride());
//register a middleware that will set a local variable on the response
app.use(function (req, res, next) {
res.locals.resLocalVar = new Date();
next();
});
app.use(app.router);
app.get('/', routes.index);
app.get('/:id', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
index.js:
exports.index = function (req, res) {
var id = req.params.id || "Nothing"
res.render('index', { renderVar: id });
};
index.jade:
extends layout
block content
p I am a global variable with value: #{globalVar}
p I am scoped to the current request/response with value: #{resLocalVar}
p I am only set on the call to render() in index.js and my value is: #{renderVar}
When you visit http://localhost:3000/[some value] you will see the values of app.locals.globalVar, res.locals.resLocalVar, and also the value of renderVar that's defined in the call to res.render() in index.js.
You can set view variables at the app level, the response level, and/or at the time of render.
Related
I just start learning NodeJS and seems amazing to me. Anyway, I'm facing a weird issue about the view rendering. Essentially I want use the MVC pattern, so I organized my project in the following way:
Inside app.js I wrote the following code:
const express = require('express');
const app = express();
require('./config/environment.js')(app, express);
require('./config/routes.js')(app);
app.listen(process.env.PORT || 3000);
Essentially, I declared the server using expressjs 'cause is indicated for MVC application, and then I placed all the configuration for the environment within envinroment.js, passing to the constructor of the module the app and the express:
module.exports = function(app, express){
app.set('development', function(){
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
app.set('production', function(){
app.use(express.errorHandler());
});
app.set('view engine', 'ejs');
app.set('views', __dirname);
if(process.env.NODE_ENV === 'production'){
app.set('port', 80);
}
};
as you can see I setted as view engine the ejs package, so in this way I can render html file within a javascript file and pass information to the view.
Then in routes.js I wrote:
module.exports = function(app){
app.get('/', function(req, res){
res.render('home.ejs', {counter: 2});
});
};
this is the code that cause the problem, infact when I load my application I get:
Failed to lookup view "home.ejs"
I also tried using:
const path = require('path');
res.render(path.join(__dirname+'/views/home.ejs'), {counter: 2});
but same problem..
Thanks in advance for any help
Add
let path = require('path');
to the start of your script.
Then, in your app.js write:
app.set("views", path.join(__dirname, "..", "views"));
instead of just "app.set('views', __dirname);".
And in your routes.js write:
res.render('home', {
counter: 2
});
I am currently learning Express ( + Node.js) and I am stuck with a strange error :
Error: Failed to lookup view "index" in views directory "../NODE_tests/Tutorial/app/views"
I have an index.jade in ../NODE_tests/Tutorial/app/views
doctype 5
html
body
h1 Hellow World!
and my app.js is ( should be ) correct :
// require the stuff we need
var express = require("express");
var logger = require("morgan");
var http = require('http');
// build the app
var app = express();
// Set the view directory to /views
app.set('views', __dirname + '/views');
// Let's use the Jade templating language
app.set('view engine', 'jade');
// Logging middleware
app.use(logger('combined'));
app.all('*', function (request, response, next) {
response.writeHead(200, { 'Content-Type': 'text/plain'});
next();
});
// Express routing system ...
app.get('/', function (request, response) {
response.render('index');
});
app.get('*', function (request, response) {
response.end('404 error! Page not found \n');
});
// start it up !
http.createServer(app).listen(8080, '127.0.0.1');
running node app.js is raising this error ... where am I wrong ?
for uncleared reason the index.jade file was named index.jade.log , but .log was invisible... ( copy paste from another file...)
sorry for this unnecessary question...
discover it using OSX info on the file
when i try to enter data in my jade form i get error message that says it is null. Can someone help me figuring out what the problem is?
app.js
var express = require('express');
var pg = require('pg');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var app = express();
var conString = "postgres://abc:123#localhost/abc";
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
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')));
// development only,
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
//app.get('/', routes.index);
app.get('/', function (req, res) {
res.render('index',
{ title : 'Home' }
)
});
app.get('/users', user.list);
app.post('/', function(req, res){
var header = req.param('header', null); // second parameter is default
var body = req.param('body', null);
console.log(header);
console.log(body);
pg.connect(conString, function(err, client, done, request, response) {
client.on('drain', client.end.bind(client));//stänger av när alla queries är klara
client.query("INSERT INTO post(member_id, title, body) VALUES ('1', $1, $2)", [header, body], function(err, result){
if (err) {
console.log(err);
}
else{
res.send("success!");
}
});
});
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
index.jade
extends layout
block content
h1= title
p Welcome to #{title}
form(action='/',method='post')
input(type='text',id='header',placeholder='header')
input(type='text',id='body',placeholder='body')
input(type='submit',name='submit',value='Submit')
layout.jade
doctype html
html
head
title= title
link(rel='stylesheet',href='/stylesheets/style.css')
body
block content
p whaddup
However if I use curl --verbose -d 'header=abcd&body=1234' http://localhost:3000 it works fine, so im fairly certain it's the jade part, but i've no clue what's wrong. I am new to nodejs and all that :)
thanks in advance.
It's the name of a form control that is submitted with the data, not the id. As it is, the only value your form is submitting is that of the submit button.
Rather it should look like this:
input(type='text', name='header', placeholder='header')
input(type='text', name='body', placeholder='body')
I am new to node and I wanted to try a simple app.post but I can't get it to work. my app.js and index.jade code is shown below. I am trying to get my app to print "hi" to the console when I enter data in the form and press submit but this is not happening.
**app.js**
/**enter code here
* 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.createServer();
app.use(express.bodyParser());
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
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('/george', function(req,res){
res.send('This is the random george page');
console.log("george");
});
app.get('/second', function(req,res){
res.render('secondpage');
});
app.get('/act', function(request, response){
console.log("hello");
});
app.post('/', function(request, response){
console.log("hi");
});
app.listen(3000);
console.log("Express server listening on port 3000");
**index.jade**
extends layout
block content
h1: a(href = 'second') George
p Welcome to your demosite George
form(method="post", action="/", name="act")
p
|Username
input(type="text", name="user")
p
|Password
input(type="text", name="pass")
p
input(type="submit", value="Submit")
First guess is everything in your jade file after the form tag needs 2 more leading spaces indent to make sure the input tags end up nested inside the form tag in the HTML. Your express JS code looks like it should work then.
i am trying to create a route for localhost:port/admin/
and i want to keep the routes.js files and view.js files in matching folders so i wont have too much spaggeti later on
but i keep getting: 500 Error: Failed to lookup view "/admin/manage_subjects"
for trying to create a new route and using same folders few the same
i have the following view folder with express
mainapp(root)
routes(folder)
admin(folder)
index.js(nested inside admin)
index.js(nested inside routes)
views(folder)
admin(folder)
admin_layout.jade(nested inside admin)
manage_subjects.jade(nested inside admin)
index.jade(nested inside views)
layout.jade(nested inside views)
code:
routes/admin/index.js
exports.index = function (req, res) {
res.render('manage_subjects',{title:'Express'});}
views/admin/manage_subjects.jade
extends admin_layout
block content
h1 = title
p Welcome to #{title}
my app.js code
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, admin_routes = require('./routes/admin/')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, repository = new (require('./domain_model/repository'))();
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());
}
//fill local subjects
repository.subjects.GetAll(function (err, data) {
if (err) throw err;
app.locals.subjects = data;
});
//append routes
app.get('/', routes.index);
app.get('/admin', admin_routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on http://localhost:' + app.get('port'));
});
I've been dealing with what I think is the same problem and figured out how to fix it. So in case someone else comes across this problem I'm posting my solution.
So here is what I had that was causing 404's and 500's
app.js
var routes = require('./routes/index');
var admin = require('./routes/admin');
app.use('/', routes);
app.use('/admin', admin);
and here was my routes/index.js
//append routes
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index', {title: 'Express'});
});
module.exports = router;
and my routes/admin.js:
var express = require('express');
var router = express.Router();
router.get('/admin', function(req, res) {
res.render('admin/index', {title: 'Express'});
});
module.exports = router;
by defining the second /admin inside the router.get() function I think I was effectively telling node to look for the html in my views folder under the following path views/admin/admin/index.ejs. So to fix that all I had to do was remove either the /admin from the router.get() or the /admin from the app.use()
So my working code now looks like this:
app.js
var routes = require('./routes/index');
var admin = require('./routes/admin');
app.use('/', routes);
app.use('/admin', admin); //I left the /admin here and instead removed the one in routes/admin.js
and here was my routes/index.js
//append routes
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index', {title: 'Express'});
});
module.exports = router;
and my routes/admin.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) { //NOTICE THE CHANGE HERE
res.render('admin/index', {title: 'Express'});
});
module.exports = router;
So making that change made it so I could have sub folders in my views folder.
Simple Answer for sub-folders inside the views folder (mine is called frontend)
click here the picture to see the folder structure
file app.js
app.set('views', [path.join(__dirname, 'frontend'), path.join(__dirname, 'frontend/locked'), path.join(__dirname, 'frontend/template'), path.join(__dirname, 'frontend/public')]);
app.set('view engine', 'pug')
I'd check out TJ's video on Modular apps on his vimeo the best part about this work flow is your code becomes really flexible and it's alot easier to stay DRY.
Additionally I would do something like this with my app.set("views")
var path = require("path");
app.set('views', path.join(__dirname, 'views'));
// you can then extend this to the example for routes
Another alternative would be something like in your app.js file:
var express require("express")
var app = express()
var routes = require("./path/to/routes")(app)
and then routes would look like:
routes = function (app) {
app.get("/route", middleWareifYou.gotIt, route.handler || function (req, res) {
res.send("some msg");
});
};
module.exports = routes
Cheers, I hope this helps!
I had a similar problem and what worked for me was setting the views folder in both the main app file and in the router file too.
So in the main app.js file I had:
app.set('views', viewsFolderPath);
And inside my router.js file I also did the same thing:
app.set('views', viewsFolderPath);