I don't know why, but when I try to view my data using req.body.newFullName I get an empty object. The post is going to the correct route but I don't know how to access the form's field data that was sent by the XMLHttpRequest.
Below is most of the code I used.
route setup app.js
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var bodyParser = require('body-parser')
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
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('/', indexRouter);
app.use('/users', usersRouter);
module.exports = app;
route details users.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
/* POST contacts */
router.post("/", function(req,res,next){
data = req.body.newFullName;
res.send(data);
})
module.exports = router;
form details index.html
...
<form id="contacts">
<label for="FullName">Full Name:</label>
<input type="text" name="newFullName" placeholder="Enter Full Name..."><br>
<input type="submit" value="Submit data">
</form>
...
js that submits form data
window.addEventListener("load",function(){
function createContact(){
var XHR = new XMLHttpRequest();
var frmData = new FormData(form);
XHR.open("POST", "http://localhost:3000/users/");
XHR.send(frmData);
};
var form = document.getElementById("contacts");
form.addEventListener("submit", function(event){
event.preventDefault();
createContact();
});
});
Thanks for your help in advance!
The problem is the client-side code; you're sending multipart/formdata but expecting application/x-www-form-urlencoded on the server.
Here's the current way to send that:
function createContact() {
const payload = new URLSearchParams(new FormData(form));
fetch("http://localhost:3000/users/", {
method: "POST",
body: payload
})
.then(rawReply => rawReply.text())
.then(reply => console.log("reply", reply))
.catch(err => console.error(err));
};
If you check the request in the browser, you'll find it now properly shows the params instead of raw text.
Related
I am trying to build a simple search form in Express using the Amadeus api. I can see the data returned to the console but upon clicking the search button on my index.js the page keeps giving me http://localhost:3001/results/undefined?q=CPT&submit= and doesn't resolve.
What am I missing here please? How do I access the response in key form to build my result page? Any help would be greatly appreciated!
app.js
require('dotenv').config();
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const indexRouter = require('./routes/index');
const postRouter = require('./routes/post');
const resultsRouter = require('./routes/results');
const usersRouter = require('./routes/users');
const app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/', postRouter);
app.use('/', resultsRouter);
app.use('/users', usersRouter);
module.exports = app;
Index.js
extends layout
block content
h1= title
div.container-fluid
div.row.justify-content-center
p Find Your Dream Kruger Safari Package!
form.form-inline.my-2.my-lg-0#searchBox(
action='/results/' + q
method='GET'
)
input.form-control.mr-sm-2(type='text', placeholder='City Code ie. LON, JHB, CPT', aria-label='Search', id='q' name='q' required)
button.btn.btn-success.my-2.my-sm-0(type='submit' id='submit' name="submit") Search
results.js
const express = require('express');
const router = express.Router();
router.get('/results/:q', (req, res) => {
const q = req.query.q;
// const result = ;
// q = JSON.stringify(q);
// console.log(result);
const searchAmadeus = require('../controllers/amadeusControl.js');
searchAmadeus.findNew(q, (err, docs) => {
if (!err) {
res.render('results', {
title: 'We Found Some Great Deals',
list: docs,
});
} else {
console.log('Error finding record :' + err);
}
});
});
module.exports = router;
post.js
const express = require('express');
const router = express.Router();
router.post('/results/:q', function(req, res) {
const q = req.body.q;
res.send(q);
// res.send(q);
//console.log(q);
});
module.exports = router;
results.pug
extends layout
block content
h1= title
p Results
div.find test #{body}
div.container
div.row
div.col-sm
p left col content
div.col-sm
tbody
each docs in list
tr
td= doc
amadeusControl.js
module.exports = {
findNew: function(q) {
// const bodyParser = require('body-parser');
// initialize the client and authenticate
const Amadeus = require('amadeus');
// console.log(process.env.AMADEUS_CLIENT_ID);
const amadeus = new Amadeus({
'clientId': process.env.AMADEUS_CLIENT_ID,
'clientSecret': process.env.AMADEUS_CLIENT_SECRET,
});
// Get list of Hotels by city code
amadeus.shopping.hotelOffers.get({
cityCode: q,
}).then(function(response) {
// console.log(response.body); // => The raw body
console.log(response.result); // => The fully parsed result
// console.log(response.data); // => The data attribute taken from the result
docs = response.result;
}).catch(function(error) {
console.log(error.response); // => The response object with (un)parsed data
console.log(error.response.request); // => The details of the request made
console.log(error.code); // => A unique error code to identify the type of error // END Do something with the returned data.
});
}};
First of all, you would access the :q parameter using the req.params object, not the req.body.
But, I think you want to use req.query instead.
Express req.query docs
If you want to use the req.body, you will need to change your form to a POST request instead of a GET request.
I'm using express.router and ejs template. I want the logic of one of my form with a POST method will be handled not in the app file (the main file of the application) but in some other file with the name 'user.js' using router.post. It returns 404 since it's trying to find the logic on the main file instead on the users.js file.
How can I route the post logic to be handled in the user.js file?
app.js file
const express = require('express');
var app = express();
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var logger = require('morgan');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
var router = express.Router();
var usersRouter = require('./routes/users');
app.use('/users', usersRouter);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
users file (routes/users.js)
var express = require('express');
var app = require('../app')
const axios = require('axios');
var bodyParser = require('body-parser');
const {User} = require('../models/userModel')
const mongoose = require('mongoose');
const mongodb = require('mongodb');
const router = express.Router();
router.get('/', function(req, res, next) {
res.render("user");
});
router.post('/userSearch', (req, res) => {
res.send(req.body.myUser);
})
module.exports = router;
user file (views/user.ejs)
<h1>Welcome to users page</h1>
<form action="/userSearch" method="POST">
Search user:<input type ="search" name="myUser"></br>
<input type = "submit">
</form>
There are few unnecessary declarations on your files but the main reason your are not reaching the router path is because you are POSTing to a NOT declared route:
<form action="/userSearch" method="POST">
should be:
<form action="/users/userSearch" method="POST">
EXTRA
Few fixes for your files:
app.js
var router = express.Router(); //not needed here
users file (routes/users.js)
var app = require('../app') //not needed here
I am trying to create a registration form which will pass data to the registration route. However, I am having trouble retrieve the form inputs in registration route. Please advice how to retrieve the form data inside the api.js file. I have tried using POSTMAN to send data to the /api/registration endpoint which did create a user in the database. When I actually use the html form to register, it failed.
HTML
<!DOCTYPE html>
<html>
<body>
<form action="/api/register" enctype="multipart/form-data" method="post">
<input name="email" type="text" placeholder="Email">
<input name="password" type="password" placeholder="Password">
<input name="passwordConf" type="password" placeholder="Confirm Password">
<input type="submit" value="Register">
</form>
</body>
</html>
Index.js
//----setting up modules
const express = require('express');
const hbs = require('hbs');
const path = require('path');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost/test');
//----define port connection on various environmentls
const port = process.env.PORT || 3000;
//----createing express app
var app = express();
// parse incoming requests
app.use(bodyParser.json());
//----use express middle-ware to utitlize public folder
// app.use(express.static(__dirname + 'public'));
app.use('/public', express.static(path.join(__dirname,'public')));
//see the first argument in above line it assigns which directory path is used to access the public file through URL
//----initializing handlebars as express view engine
app.set('view engine', 'hbs');
//----define handlebars partials and helpers
hbs.registerPartials(__dirname + '/views/partials');
//----define helper to get current year
hbs.registerHelper('getDate', ()=>{
return new Date().getFullYear();
});
//----define routes
app.get('/', function (req, res) {
res.render('home.hbs')
})
// include routes
app.use('/api', require('./routes/api'));
app.use('/', require('./routes/page'));
//----connecting to port
app.listen(port,()=>{
console.log(`success connection to port ${port}`);
})
Api.js Route
var express = require('express');
var router = express.Router();
var {User} = require('./../models/user');
var {authenticate} = require('./../middleware/authenticate');
var _ = require('lodash');
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json()
var urlencodedParser = bodyParser.urlencoded({ extended: false })
router.post('/register',function (req, res) {
console.log(req.body);
});
module.exports = router;
pages.js
var express = require('express');
var router = express.Router();
router.get('/register', function (req, res) {
res.render('register.hbs', {title:"REGISTER"} )
})
router.get('/login', function (req, res) {
res.render('login.hbs', {title:"LOGIN"} )
})
module.exports = router;
Here is my recommendation:
Create a file called routes.js and include ALL your routes there and import it.
var express = require('express');
var router = express.Router();
app.get('/', function (req, res) {
res.render('home.hbs')
})
router.get('/api/register', function (req, res) {
res.render('register.hbs', {title:"REGISTER"} )
})
router.post('/api/register',function (req, res) {
//do your post logic here
console.log(req.body);
});
router.get('/login', function (req, res) {
res.render('login.hbs', {title:"LOGIN"} )
})
module.exports = router;
in your Index.js :
//Make sure the route is correct
app.use('/', require('/routes/routes.js'));
Doing this, I expect the error to be solved,
Good luck!
I have an app where I am trying to move the routes to separate files. I keep getting a CANNOT GET/ when trying to use express router. I've set it up the same way I have it in other apps but can't get it to work.
this is in my routes folder: index.js
var express = require('express');
var router = new express.Router();
var Blog = require('../models/blogpost');
var User = require('../models/user');
var passport = require('passport');
router.get("/", function(req, res){
Blog.find({}, function(err, blogs){
if(err){
console.log(err);
} else {
res.render("index", {blogs: blogs});
}
});
});
module.exports = router;
This is my app.js file:
var methodOverride = require('method-override'),
LocalStrategy = require('passport-local'),
bodyParser = require('body-parser'),
nodeMailer = require('nodemailer'),
passport = require('passport'),
mongoose = require('mongoose'),
express = require('express'),
request = require("express"),
router = express.Router(),
User = require('./models/user'),
Blog = require('./models/blogpost'),
Comment = require('./models/comment'),
middleware = require('./middleware'),
app = express(),
request = require('request'),
indexRoutes = require('./routes/index');
//==================================
//APP CONFIG
//==================================
// mongoose.connect("mongodb://localhost/amy_blog");
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride("_method"));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(function(req, res, next){
res.locals.currentUser = req.user;
next();
});
app.use(express.static(__dirname + "/public"));
app.use('/', indexRoutes);
=====================
app.listen(process.env.PORT, process.env.IP, function(){
console.log("================================");
console.log("The Blog server has started!");
console.log("================================");
});
Any help would be greatly appreciated. Been racking my mind about this one for awhile.
You don't want to be creating a new instance of express.Route().
In your routes file remove the new keyword from where you assign the router variable. Probably just a typo.
As per the docs https://expressjs.com/en/guide/routing.html
express.Router() instance is a middleware and routing system for Express.js. In your code, there are two mistakes you are making:
Calling express.Router() with the new keyword
Not loading the router module in the app
Below is a simple approach you can use to make your application work:
const express = require('express');
const app = express();
const router = express.Router();
// This route handler is for demo purposes,
// you can replace it with your own route and add other routes as desired
router.get("/", (request, response) => {
response.json({"message": "app works!"});
});
app.use("/", router); // Load the router module
app.listen(8080, () => 'Server started and is listening on port: 8080');
I am new to nodejs and express in general. I am trying to get a POST value from a html page using body-parser. I tried following several suggestions in SO but unable to make it work for me.
Here is the code. Any pointers will be highly appreciated. Thanks in advance.
Server.js
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var Subscribe = require('./models/subscribe');
mongoose.connect('CREDENTIALS');
var app = express();
app.use(bodyParser.json(), bodyParser.urlencoded({ extended: false }));
var port = 3000;
var router = express.Router();
router.get('/', function(req, res) {
res.json({ message: 'Test...' });
});
var subscribeRoute = router.route('/subscribe');
subscribeRoute.post(function(req, res) {
var subscribe = new Subscribe();
subscribe.email = req.body.email_notify;
console.log(subscribe);
subscribe.save(function(err) {
if (err)
res.status(500).send(err);
res.status(200);
});
});
app.use('/api', router);
app.listen(port);
index.html
<form action="http://localhost:3000/api/subscribe/" method="POST" enctype="application/json">
<input type="text" onfocus="if (this.value=='E-mail Address') this.value = ''" onblur="if (this.value=='') this.value = 'E-mail Address'" value="E-mail Address" id="email_notify" name="email_notify" />
<button id="notify_me" ontouchstart="">Notify Me!</button><br/>
</form>
Thanks
Sujith
change this
app.use(bodyParser.json(), bodyParser.urlencoded({ extended: false }));
To this
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
Make <input type='submit'> instead of the <button> and remove enctype form the form.
Also in Chrome open developer tools, network tab and check that the request is sent to your server at all