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 });
});
Related
I am trying to pass a string from the frontend into the backend, but I have hit a roadblock. I am using Node, Express, Body Parser, EJS, and PostgreSQL. My basic file system is this:
– app
|– api
| |– thing.js
|
|– index.js
– views
|– pages
|– index.ejs
I have a form submission in index.ejs that passes data to the index.js file:
index.ejs
<form action="/creatething" method="post">
<h1>Make a thing</h1>
<p> What is your thing called?
<input name="wtitle" type="text">
</p>
<p> What is your name?
<input name="cuser" type="text">
</p>
<input type="submit" value="Submit">
</form>
The above code triggers /creatething, which is placed in index.js
index.js
const express = require ('express');
const thingRouter = require('./api/thing');
const bodyParser = require("body-parser");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: false}));
app.use('/thing', thingRouter);
app.get('/', function (req, res){
res.render('pages/index');
});
app.post('/creatething',(req,res)=>{
console.log('clicked '+ req.body);
});
module.exports= app;
With this I am able to create a message in the console that prints the user input from the form. However, I am trying to send this data to a database through code in thing.js:
thing.js
const {Router} = require('express');
const router = new Router();
router.get('/',(req,res)=> {
console.log(req.body);
// Placeholder for working code that stores thing in database :)
});
module.exports = router;
The problem here is that I don't know how to pass the req.body data from the index.js file to the thing.js method that inserts the data into the database. I could just add the database code into the index.js file, but I was trying to keep things more separated and learn about routing/mounting. What am I missing at this point?
You have to change a few things in your thing.js file. Only few lines of code is required instead of importing Router from express and add some extra routes.
Just copy below code and paste to your respective files.
thing.js
const get = (req, res) => {
console.log(req.body);
}
module.exports = get;
index.js
const express = require ('express');
const get = require('./api/things');
const bodyParser = require("body-parser");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: false}));
app.get('/', function (req, res){
res.render('pages/index');
});
app.post('/creatething', (req,res)=>{
get(req,res);
});
app.listen(4000, () => {
console.log('App is running on port: 4000');
});
module.exports= app;
Hope this helps you solve the issue.
I'm currently trying to implement file-uploads for my application, in which I use ReactJS, node.js with express, and MongoDB and mongoose. I'm using multer middleware for fileuploads, however, despite looking at all similar questions here on SO and also looking it up, I can't seem to get it to work.
This is my React form:
addUser (event) {
var formfile = new FormData();
formfile.append("file", this.state.filesToBeSent);
axios.post('adduser',
JSON.stringify({
entry: this.state.currname,
passwrd: this.state.currpasswrd,
formfile : formfile
}), {
headers: {"Content-Type": "application/json"}
}
)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<form onSubmit={this.addUser} encType="multipart/form-data" >
<input value={this.state.currname} />
<input value={this.state.currpasswrd} />
<input type="file" value={this.state.filesToBeSent} name="file" />
<button type="submit" >Add</button>
</form>
);
}
This is my node.js file:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var User = require('../models/User.js');
var bodyParser = require('body-parser');
var multer = require("multer");
const uuidv4 = require("uuid/v4");
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cd(null, "./uploads");
},
filename: (req, file, cb) => {
const newFilename = `${uuidv4()}${path.extname(file.originalname)}`;
cb(null, newFilename);
},
})
const upload = multer({ storage });
router.post("/", upload.single("file"), (req, res) => {
console.log(req.file + " and exit.");
});
module.exports = router;
I'm not doing anything with the text-inputs just yet, because I wanted to get the file upload to work first.
I tried out a variety of things, like using async(req, res) in router.post(). I tried using x-www-form-urlencoded as content-type and to only send the file without text-inputs( I specified formfile as data to be sent without the whole JSON.stringify(), however, I didn't manage to get it to work.
Can anyone spot a mistake in my code? Or does anyone have any other ideas about how to get it to work?
Edit:
Setting up the adduser-route in 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 adduser = require('./routes/adduser');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
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('/adduser', adduser);
Did you test your post endpoint? You can use a rest client such as Postman or Insomnia just to make sure that this is not the problem. Send a POST request to the endpoint and see if it gets invoked.
Then I guess you should use "/adduser" on your client and not "adduser" if you endpoint is exposed at "localhost:port/adduser". Your code doesn't show how you set up the route in the node.js code.
Finally you may want to use an higher level component to perform the upload, which can handle multipart for you in case you upload larger files. I found the combination react-dropzone + Multer being quite convenient.
try this :
router.post("/", upload.single("formfile"), (req, res) => {
console.log(req.formfile + " and exit.");
});
i think the headers should be:
{"Content-Type": "multipart/form-data"}
instead of application/json.
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);
});
I'm using node with express#4.13.4 and body-parser#1.13.3.
My jade page has for instance this property:
input(type='text',class='form-control', placeholder="Username", name='username', id="username")
The JavaScript code looks like this:
var bodyParser = require('body-parser');
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path');
var app = express();
var favicon = require('favicon')
app.use(bodyParser.json());
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use( function(req, res, next){
app.locals.pretty = true
next()
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static(path.join(__dirname, 'public')));
app.get('/create', function(req,res) {
res.render("create");
});
app.get('/creation', function(req,res) {
console.log("creation")
console.log(req.body)
});
The create page is the first opened and there is also the input field username, but the request body is empty in the /creation function. Can anyone help ?
You need to submit the form using POST method and alter the function:
app.post('/creation', function(req,res) {
console.log("creation")
console.log(req.body); // here will show the values of inputs submited
});
More about express routes.
As we understood body parse will work on the submit of the form or json with POST request. in this case make sure you are submitting the form correctly, you can see the POST request in firebug or other tool. Once its done correctly you will be able to see the body elements by req.body.username
you can have simple form like.
<form action='post' ..>
<input name='username' ..>
<input type='submit' ..>
</form>
Also I seen two times middleware app.use(bodyParser.json()); use. in case you missed it.
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;