I am new to NodeJS and ExpressJS development (a week old or so). I am trying to create a web application in NodeJS using ExpressJS framework. One of the things I am trying to do is build a registration form for my app. I have installed body-parser middleware using the npm to read form data.
I am using HoganJS as my template framework. I have a page in my views folder named register.hjs. This page has a form
<form method="post">
<input type="text" name="name">
<input type="text" name="age">
<input type="submit">
</form>
I am struggling with these two issues:
How to read form values in the .js
How to redirect a user to a different page once form is submitted.
This is what I am trying to do (it might be incorrect though).
In my app.js
//get
app.get('/register', routes.register);
//post
app.post('/welcome', routes.welcome);
In my index.js
/* GET about page.*/
exports.register = function(req, res) {
res.render('register');
};
/*POST registered user*/
exports.welcome = function(req, res) {
// pull the form variables off the request body
var name = req.body.name;
var age = req.body.age;
//just to make sure the information was read
console.log(name);
console.log(age);
res.render('welcome');
};
I am pretty sure I am missing something cause when I run my server it gives an error saying :
Error: Route.get() requires callback functions but got a [object Undefined]
What am I doing wrong? Is there any elegant way to read form data and redirect users to different pages?
Thanks.
--------------------------- Update ----------------------------
Here is the rest of the app.js Code
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//routes to the pages
var routes = require('./routes/index');
var users = require('./routes/users');
var register = require('./routes/register');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views')); //app.set('the name of your view folder', )
app.set('view engine', 'hjs');
//get
app.get('/register', routes.register);
//post
app.post('/welcome', routes.welcome);
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/register', register);
//error handlers
//error handlers
module.exports = app;
For Simple understanding how express works for form understand this code :
After understanding this code , use router and other body parser configuration---
var express = require('express');
/*
* body-parser is a piece of express middleware that
* reads a form's input and stores it as a javascript
* object accessible through `req.body`
*
* 'body-parser' must be installed (via `npm install --save body-parser`)
* For more info see: https://github.com/expressjs/body-parser
*/
var bodyParser = require('body-parser');
// create our app
var app = express();
// instruct the app to use the `bodyParser()` middleware for all routes
app.use(bodyParser());
// A browser's default method is 'GET', so this
// is the route that express uses when we visit
// our site initially.
app.get('/', function(req, res){
// The form's action is '/' and its method is 'POST',
// so the `app.post('/', ...` route will receive the
// result of our form
var html = '<form action="/" method="post">' +
'Enter your name:' +
'<input type="text" name="userName" placeholder="..." />' +
'<br>' +
'<button type="submit">Submit</button>' +
'</form>';
res.send(html);
});
// This route receives the posted form.
// As explained above, usage of 'body-parser' means
// that `req.body` will be filled in with the form elements
app.post('/', function(req, res){
var userName = req.body.userName;
var html = 'Hello: ' + userName + '.<br>' +
'Try again.';
res.send(html);
});
app.listen(80);
app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hjs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
module.exports = app;
index.js:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/register', function(req, res) {
res.render('register');
});
router.post('/welcome', function(req, res) {
console.log(req.body.name);
console.log(req.body.age);
});
module.exports = router;
Related
I'm still fairly new to Express.js. I have a question about sending form data to an existing template. I have two routes which have template views associated with them. One page has a form on it and I want to take inputs from that form to populate the other template of the other route. I'm using Hanglebars for my template engine.
I've found a lot of helpful answers here (this one especially Cannot POST form node.js - express ), but none that quite answer my question.
I know how to post to create a new page with the form data. Like this:
router.post('/game', function(req, res) {
res.send(req.body.username);
});
But how do I get req.body.username accessible to a handlebars template? I've been reading various tutorials and it looks like I need to do something with next() in app.use('/game', game);. But I'm getting lost as to what exactly that is.
Here's a simplified version of my code.
My main server file:
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var http = require('http').Server(app);
var path = require('path');
var io = require('socket.io')(http);
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var routes = require('./routes/index');
var game = require('./routes/game');
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/game', game);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
http.listen(3000, function(){
console.log('listening on *:3000');
});
My route file "index.js":
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', {
title: 'Pick a Player',
});
});
module.exports = router;
Here is the form on index.handlebars (just the form):
<form method="post" action="/game" novalidate name="pick-a-player" id="pickAPlayer" class="form-box">
<p>What is your name?</p>
<input type="text" name="username" placeholder="name">
<p>Please select a player</p>
<label>
<input type="radio" name="player" value="Jane" checked> Jane<br>
<input type="radio" name="player" value="Sue"> Sue<br>
<input type="radio" name="player" value="Anne"> Anne<br>
</label>
<input type="submit" value="Start the game" id="submitCharacterForm">
</form>
I know I need to use post to get the data through req.body. But I'm getting the template through .get(). How do get the two to communicate?
Here's the route for game.js
var express = require('express');
var exphbs = require('express-handlebars');
var app = express();
var router = express.Router();
/* GET Game page. */
router.get('/', function(req, res) {
res.render('game', {
title: 'Let's Play',
username: req.body.username,
player: req.body.player
});
});
module.exports = router;
When the value of player gets called on game.handlebars, it looks like this:
<p class="player-card">{{player}}</p>
If I'm understanding this correctly, the main form will have two values on the request body: username and player.
This form will make a POST request to /game according to your form block:
<form method="post" action="/game" ...>
You handle this POST request with the following route handler:
router.post('/game', function(req, res) {
res.send(req.body.username);
});
And you want to send the username and player values to your game template correct?
If I'm understanding this correctly, you can either res.redirect with data or simply render a different view with the data:
router.post('/game', (req, res) => {
const { username, player } = req.body
res.render('play-game', { username, player });
});
Ive been recently learning how to use node.js to create a backend login system with passport. Im running it locally with a mongoDB. The url I use to access it is http://localhost:3000. Now when I go to that url instead of displaying my index.handlebars page it routes me to http://localhost:3000/users/login. Im wondering why this is? Ill provide a few files let me know if there is anything else you may need.
Not sure what else you would need, but I have looked through my code hundreds of times and cant find out why. My routes seem fine, my static folder seems fine. Im just lost. Any help would be appreciated.
My directory looks like this,
loginapp-master
-models
-users.js
-node_modules
-public
-css
-fonts
-js
-routes
-index.js
-users.js
-views
-layouts
-layout.handlebars
-index.handlebars
-login.handlebars
-register.handlebars
.gitignore
app.js
package-lock.json
package.json
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var exphbs = require('express-handlebars');
var expressValidator = require('express-validator');
var flash = require('connect-flash');
var session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var mongo = require('mongodb');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/loginapp');
var db = mongoose.connection;
var routes = require('./routes/index');
var users = require('./routes/users');
// Init App
var app = express();
// View Engine
app.set('views', path.join(__dirname, 'views'));
app.engine('handlebars', exphbs({defaultLayout:'layout'}));
app.set('view engine', 'handlebars');
// BodyParser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// Set Static Folder
app.use(express.static(path.join(__dirname, 'public')));
// Express Session
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
// Passport init
app.use(passport.initialize());
app.use(passport.session());
// Express Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
// Connect Flash
app.use(flash());
// Global Vars
app.use(function (req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
res.locals.user = req.user || null;
next();
});
app.use('/', routes);
app.use('/users', users);
// Set Port
app.set('port', (process.env.PORT || 3000));
app.listen(app.get('port'), function(){
console.log('Server started on port '+app.get('port'));
});
I saved email in session in my login.js
router.get('/signin',function(req,res,next) {
res.send(req.session.email);//here i can get email from session as well
console.log("email inside ./signin in login.js "+req.session.email);
});
router.post('/login', function(req, res) {
req.session.email=req.body.email; //get email from form body
console.log(req.session.email); // here i can get my email in console
res.redirect('/') //want to redirect to home
});
I want to access email from session in my index.js
var session;
router.get('/', function(req, res, next) {
session=req.session;
console.log("your mail is"+session.email);
});
And this is app.js config
var
express = require('express');
var app = express();
var path = require('path');
var connection=require('./models/connection');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session=require('express-session');
var index = require('./routes/index');
var users = require('./routes/users');
var login=require('./routes/login');
var debug = require("debug");
var clc = require('cli-color');
var router=express.Router();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(favicon(path.join(__dirname, 'public/images/', 'favicon.gif')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser("secretkey"));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/assets', express.static(__dirname + '/assets'));
app.use(session({secret: 'secretkey',saveUninitialized: true,resave: true}));
app.get('/login',login);
app.post('/login',login);
app.get('/signin',login);
app.get('/',index);
module.exports = app;
Want some thing like this we can do in php
<!-- first page -->
<?php
session_start();
$_SESSION['myvar'] = 'hello';
?>
<!-- second page -->
<?php
session_start();
echo $_SESSION['myvar']; // it will print hello
?>
I tried these and some more answer but none of them solve my problem
NodeJS express-session req.session is undefined
req.session is undefined in Node?
How to use req.session data in an other javascript file expressjs
So, I tried your code as-is as best I could (copied and pasted from yours, added files that were needed that you didn't post here, e.g. a server.js file that actually starts listening on a port), and it worked as-is with just one change.
Your index.js file does not ever actually send anything back to the client. Note your code:
var session;
router.get('/', function(req, res, next) {
session=req.session;
console.log("your mail is"+session.email);
});
There's no res.send or res.render called, so it's going to just hang. It has nothing to do with the session value, though, the console.log statement still prints out the correct email value that was posted before.
Try:
var session;
router.get('/', function(req, res, next) {
session=req.session;
console.log("your mail is"+session.email);
res.send(session.email);
});
app.js:
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var person = require('./routes/person');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/person', person);
module.exports = app;
routes/person.js:
var express = require('express');
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
var router = express.Router();
/* GET page. */
router.get('/', function (req, res) {
res.render('person', {
message: 'Person works'
});
});
router.post('/', urlencodedParser, function (req, res) {
res.send('Thank you!');
console.log(req.body.firstname);
console.log(req.body.lastname);
});
views/person.pug:
extends layout
block content
h1 Welcome #{id}
p= message
br
h2= qstr
br
form(method='post', action='/person')
label First name
input#firstname(type='text')
br
label Last name
input#lastname(type='text')
input(type='submit', value='Submit')
Questions:
1) Is it necessary in every route to add?:
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
2) Why do I get this:
1.You don't need to use body-parser in every route. Body-parser is a middleware which is used to obtain data from application/x-www-urlencoded content type. So if you're sure sure that data you will get in your body is not x-www-urlencoded type, you don't need to use it.
2.Please check if you are passing the data in post request. You can use chrome extension postman to form any kind of query.
I don't know what I touched but suddenly it stopped serving my static files.
I have the following architecture:
App
Routes
Models
public
views
css
js
server.js
The Error:
Error: Cannot find module 'html'
at Function.Module._resolveFilename (module.js:325:15)
...
at /Users/.../vintageAddiction/app/routes/indexRoutes.js:12:11
indexRoutes.js:
var express = require('express');
var passport = require('passport');
var indexRouter = express.Router();
indexRouter.route('/').get( function(req, res) {
res.render('index.html'); // load the index.ejs file
});
module.exports = indexRouter;
SERVER.JS:
// server.js
// set up ======================================================================
// get all the tools we need
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var configDB = require('./app/config/configDB.js');
// configuration ===============================================================
mongoose.connect(configDB.url); // connect to our database
require('./app/config/passport')(passport); // pass passport for configuration
// routes ======================================================================
var routes = require('./app/routes/indexRoutes.js'); // load our routes and pass in our app and fully configured passport
var adminRoutes = require('./app/routes/adminRoutes.js');
// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser()); // get information from html forms
// app.set('view engine', 'ejs'); // set up ejs for templating
// required for passport
app.use(session({ secret: 'vintageisthelaw' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
app.use('/', routes);
app.use('/admin', adminRoutes);
// set static files location
// used for requests that our frontend will make
app.use(express.static(__dirname + '/public/'));
app.set('views', __dirname + '/public/views');
app.set('view engine', 'jade');
// launch ======================================================================
app.listen(port);
console.log('The magic happens on :\n\n http://localhost:'+ port+'\n\n');
link to server.js
I've seen something similar to :
app.use(express.static(__dirname + '/public/views/'));
But I don't really understand why is not working
Hope you can help me guys !
In express.js order of middleware declaration is very important. You must define express.static middleware earlier than any of the routes:
SERVER.JS:
.. require
// logger must be defined first if you want log all the requests
app.use(morgan('dev'));
// after that you should define express.static middleware
app.use(express.static(__dirname + '/public/'));
app.set('views', __dirname + '/public/views');
app.set('view engine', 'jade');
// cookie and body parser must be defined before passport and session middleware
app.use(cookieParser());
app.use(bodyParser());
app.use(session({ secret: 'vintageisthelaw' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
// your routes must be defined in the end
app.use('/', routes);
app.use('/admin', adminRoutes);
app.listen(port);
console.log('The magic happens on :\n\n http://localhost:'+ port+'\n\n');