I'm running a server in nodejs with express to serve an html form within the file index.html to a client like this:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser());
app.get('/', function(req, res){res.sendfile('index.html');});
app.post('/', function(req, res){
res.json(req.body);
});
app.listen(8080);
req.body gives me the form input. Now I need to send back req.body to the client, and to do this I'm using ajax on the client side (inside index.html) like this:
var data;
$('#submit').click(function()
{
console.log('Button Clicked');
$.ajax({
url: '/',
type:'POST',
data: data,
dataType: 'json',
}).done(function(data) {
console.log(data);
});
})
However when I click the button submit I get Object {} in the browser console and not the form input.
What am I missing here?
There are two issues in your code:
First, as the comments mention, bodyParser() is deprecated, you should be using the specific bodyParser middlewares (json, text, urlencoded, raw). So in your case:
app.use(bodyParser.json())
Second, your client side call to jQuery.ajax should stringify your data. Like this:
$('#submit').click(function()
{
console.log('Button Clicked');
$.ajax({
url: '/',
type:'POST',
data: JSON.stringify(data),
dataType: 'json',
}).done(function(data) {
console.log(data);
});
})
Related
I'm new to using nodeJS and npm modules.
Using the module twit, I can do a GET request to the Twitter API and search tweets.
var Twit = require('twit')
var T = new Twit({ `login details`})
T.get('search/tweets', { q: 'banana since:2011-07-11', count: 100 }, function(err, data, response) {
console.log(data)
})
I am trying to build a simple user browser page, where a user can enter their own query parameters. I understand that modules are server side, and we can't use them on the browser. I also can't use browserify because twitter uses Oauth method which means you can't access it from the browser.
Is there a way to pass query parameters from the browser back to the server code, and then to pass that result back to the browser?
T.get('search/tweets', { q: {user options}, function(err, data, response) {
console.log(data)
})
We can use socket.io for the streaming twitter data, but how can I use it for the REST API?
Nodejs
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const Twit = require('twit');
...
const T = new Twit(LOGIN_DETAILS);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/search', function (req, res, next) {
T.get('search/tweets', {q: req.body.searchQuery, count: 100}, function (err, data, response) {
return res.json({
data: data
});
});
});
Client Side
...
$.ajax({
url: "{API_URL}/search",
type: "POST",
dataType: 'json',
data: JSON.stringify({
searchQuery: SearchQuery
}),
contentType: "application/json; charset=utf-8",
success: function (msg) {
console.log(msg);
// do something with the response
}
});
$ is jQuery, read more about jquery ajax
when pressing a button this code gets executed
function submitData() {
$.ajax({
type: 'GET',
url: '/questionnaire/submit', // listen to a route
dataType: "json",
data: JSON.stringify({ // some test data
satisfactory: "house",
improvement: "bla",
rating: "this is a text"
})
}).done(function () {
$(location).attr('href', '/sendOff'); // redirect to another route
}).fail(function () {
console.log("Error");
});
}
and the server is listening on this
app.get('/questionnaire/submit', function (req, res) {
var data = req.query; // Get the data object from the Ajax call
console.log(data);
res.send(null); // Send nothing back
});
Whenever pressing the button, "Error" gets logged in the console. The Ajax call always fails.
Even when writing res.send("Success"); the client will log "Error". What am I missing?
Update:
I installed the body parser middleware and use this code now
my app.js
const path = require('path');
const express = require('express');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
const handlebars = exphbs.create({
defaultLayout: 'index',
extname: 'hbs'
});
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
require('./Server/Routes/questionnaire')(app);
require('./Server/Routes/sendOff')(app);
app.engine('hbs', handlebars.engine);
app.set('view engine', 'hbs');
app.use(express.static(path.join(__dirname, 'Public')));
app.listen(8888, function () {
console.log('Server running on port 8888');
});
my route
module.exports = function (app) {
app.get('/questionnaire', function (req, res) {
res.render('questionnaire');
});
app.post('/questionnaire/submit', function (req, res) {
var data = req.body;
console.log(data);
res.send(null);
});
};
and my client function
function submitData() {
$.ajax({
type: 'POST',
url: '/questionnaire/submit',
dataType: "json",
data: JSON.stringify({
satisfactory: $("#edtSatisfactory").val(),
improvement: $("#edtImprovement").val(),
rating: currentRating / ratingElements.length
})
}).done(function () {
$(location).attr('href', '/sendOff');
}).fail(function () {
});
}
And when executing the Ajax call the client still runs into .fail()
Client request is :
function submitData() {
$.ajax({
type: 'POST',
url: '/questionnaire/submit', // listen to a route
dataType: "json",
data: {
satisfactory: "house",
improvement: "bla",
rating: "this is a text"
}
}).done(function () {
$(location).attr('href', '/sendOff'); // redirect to another route
}).fail(function () {
console.log("Error");
});
}
and the server is listening on this Using bodyParser middleware in your node backend
:
app.post('/questionnaire/submit', function (req, res) {
var data = req.body; // Get the data object from the Ajax call
console.log(data);
res.end(); // Send nothing back
});
You're using a GET http method, which shouldn't take body, you should instead append your data to the back of the url. Or if you want to use a body, then switch to a POST.
url: '/questionnaire/submit?satisfactory=house&improvement=bla&rating=sometext
If you're using POST don't forget:
'Content-Type': 'application/json',
Edit: On the server you need to parse the JSON request, this is best done with a middleware called body-parser:
npm install --save body-parser
const bodyParser = require('body-parser');
app.use(bodyParser.json());
This will parse your JSON and add it to req.body.
Try this..
Client Side
function submitData() {
$.ajax({
type: 'POST',
url: '/questionnaire/submit', // listen to a route
'Content-Type': 'application/json',
data: JSON.stringify({"satisfactory": "house", "improvement": "bla", "rating": "this is a text"})
}).done(function () {
console.log('hi')
}).fail(function () {
console.log("Error");
});
}
On server Side:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.post('/questionnaire/submit', function (req, res) {
var data = req.body
console.log(data);
res.send(null); // Send nothing back
});
You have to install body-parser library using following command.
npm install --save body-parser
It will log "Hi" as ajax done is called. BTW You have redirected the page to 'sendOff' in your question.
If you are not understanding anything plz comment below.
You just have to replace
dataType: "json",
with this:
'Content-Type': 'application/json'
in $.ajax request
Hope this will work.. I have tried & tested.
My client side
$.post("http://localhost:3000/scrape",
{
data: 'something'
},
function(data, status){
console.log(data);
});
What I do in node.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.post('/scrape', function (req, res) {
console.log(req.body.data)
});
But I got undefined in console.log(req.body.data), any idea why?
Your data must be of json format. since you are using bodyParser.json().
Try setting the http header, Content-type as application/json in your $.post call and send a valid json structure as data
$.ajax({
url: "scrape",
type: "POST",
data: JSON.stringify({ someData : "someData}),
contentType:"application/json; charset=utf-8",
dataType:"json",
success: function(data){
console.log(data)
},
error: function(){
console.log('error in sending request')
}
})
console.log(req.body.data)
returns undefined because the data is in req.body you should console.log(req.body)
and add app.use(bodyParser.urlencoded({extended: false})); so that data not in json format can also be parsed.
if you want req.body.data have data then make request like
$.post("http://localhost:3000/scrape",
{
data: {data: 'something'}
},
function(data, status){
console.log(data);
});
also your request is not sending any response you need to do something like
app.post('/scrape', function (req, res) {
console.log(req.body.data)
res.status(200).json({data: reqr.body.data});
});
hope it helps :)
How do I parse my JSON with external middleware now that Express doesn't carry a body parser?
For a while, I was using Express bodyParser to receive and respond to JSON posts to the server. Each time I started up the server, express said something about bodyParser being removed soon, and sure enough, I've updated and now JSON requests seem to be showing null.
So I didn't understand how middleware worked, and had followed an express tutorial to use the body parser. Now, using separate body parser middleware, it seems I'm doing it wrong.
Before, my syntax was:
app.use(express.bodyParser());
Now, with the module body-parser as middleware, it's like this:
app.use(bodyParser.json());
And an example as a whole:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
function listen() {
app.use(bodyParser.json());
app.post('/login', function (req, res) {
var username = req.body.username;
var password = req.body.password;
console.log('User ' + username + ' is attempting login...');
validate(username, password, function (err, result) {
if (err) loginFail(req, res, err);
else loginSucceed(req, res, result);
});
});
app.listen(3333);
}
listen();
I tried express.json() as the middleware, but that triggers the fatal error:
Error: Most middleware (like json) is no longer bundled with Express
and must be installed separately. Please see
https://github.com/senchalabs/connect#middleware.
That link leads to the body-parser middleware that I'm using via app.use(bodyParser.json()).
Update:
Using bodyParser.json() results in no error, but the data values are null:
User undefined is attempting login...
My client code should be fine, but here it is for completeness:
function sendLogin() {
popLogCreds(creds);
var loginCredentials = {
"username": creds.username,
"password": creds.password
};
console.log("Sending login credentials: " +
JSON.stringify(loginCredentials, null, 4));
request = $.ajax({
url: "http://54.186.131.77:3333/login",
type: "POST",
crossDomain: true,
data: loginCredentials,
dataType: "json",
error: function () {
postError("Uh Oh! The Officeball server is down.");
},
success: function (data) {
var ParsedData = data;
sessionStorage.username = creds.username;
sessionStorage.password = creds.password;
sessionStorage.fname = ParsedData.fname;
sessionStorage.lname = ParsedData.lname;
sessionStorage.rank = ParsedData.rank;
console.log(sessionStorage);
window.location.replace("app.html");
}
});
}
Which results in:
Sending login credentials: {
"username": "jonathan#evisiion.com",
"password": "J******!"
}
And then the result is the POST's error output, which is, as above:
error : function () {
postError("Uh Oh! The Officeball server is down.");
}
Don't take that error message literally. Just means an error happened. The server is, in fact, getting that request, as shown up above.
By default, $.ajax() sends data URL-encoded as mentioned in the description of the processData option:
By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded".
The body-parser that corresponds to that Content-Type and format is urlencoded():
app.use(bodyParser.urlencoded());
If you'd rather use JSON for the request, you'll need to provide the data already formatted as such along with a matching contentType that bodyParser.json() recognizes:
request = $.ajax({
url: "http://54.186.131.77:3333/login",
type: "POST",
crossDomain: true,
data: JSON.stringify(loginCredentials),
contentType: 'application/json',
dataType: 'json'
// ...
});
Note for cross-domain: With these modifications, the server will have to handle preflight OPTIONS requests for the route.
And, note that a bodyParser isn't needed for HEAD or GET requests as the data is included in the URL rather than the body. Express parses that separately into req.query.
In your node code,
make sure you put these two lines of code
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyparser.urlencoded({ extended: false }));
app.use(bodyparser.json());
......then your other code follows..
enjoy...
This is to start with a very basic page: HTML Form, a button, and a div-box.
.click of the button would POST the Form data through AJAX.
The data is to be stored in MongoDB, and retrieved into the div-box without a page-refresh.
AJAX from index.html:
$(document).ready(function()
{
// handle button clicks
$('#buttonID').click(function() {
// make an ajax call
$.ajax({
dataType: 'jsonp',
jsonpCallback: '_wrapper',
data: $('#formID').serialize(),
type: 'POST',
url: "http://localhost:9999/start",
success: handleButtonResponse,
});
});
function handleButtonResponse(data)
{
// parse the json string
var jsonObject = JSON.parse(data);
$('#reponseID').append( jsonObject.message );
}
});
app.js:
var express = require('express'),
app = express();
cons = require('consolidate');
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server;
app.engine('html', cons.swig);
app.set('view engine', 'html');
app.set('views', __dirname + "/views");
var mongoclient = new MongoClient(new Server('localhost', 27017,
{ 'native_parser' : true }));
var db = mongoclient.db('database_name');
app.get('/', function (req, res) {
db.collection('collectionName').find({}, function (err, doc) {
res.render('index', doc);
});
response.writeHead(200, {"Content-Type:": "application/json"});
var submittedPost = {};
submittedPost['message'] = 'Proof that Node and Mongo are working..';
response.write( "_wrapper('" );
response.write( JSON.stringify(submittedPost) );
response.write( "')");
response.end();
});
app.get('*', function (req, res) {
res.send("404..", 404);
});
mongoclient.open(function (err, mongoclient) {
if (err) throw err
app.listen(9999);
console.log("Express server started on port 9999");
});
How/Where does the JSON connect to/from MongoDB?
Also, does Express require a templating engine, such as Consolidate? If so, how/where does that fit in?
Few suggestions
Regarding the ajax call in index.html
If your index.html is served by the same server, then please don't use a cross domain call. The url property in $.ajax could be a relative url like /start.
Also you can think of not using jsonp request.
the call could be like
$.ajax({
dataType: 'json',
data: $('#formID').serialize(),
type: 'POST',
url: "./start",
success: handleButtonResponse,
});
How/Where does the JSON connect to/from MongoDB?
In you ajax call you are requesting for ./start, So the same route should be made in your express server. like
app.get('/start', function (req, res) {
db.collection('collectionName').insert({req.data}, function (err, doc) {
//rest of code
});
});
does Express require a templating engine, such as Consolidate? If so, how/where does that fit in?
You have many options for templating like jade,ejs,hbs and so on.
If you use jade or any of them your html rendering code in express routes will get simplified.
without a templating engine
response.writeHead(200, {"Content-Type:": "application/json"});
var submittedPost = {};
submittedPost['message'] = 'Proof that Node and Mongo are working..';
response.write( "_wrapper('" );
response.write( JSON.stringify(submittedPost) );
response.write( "')");
response.end();
with a templating engine like jade (now pug)
var submittedPost = {};
submittedPost['message'] = 'Proof that Node and Mongo are working..';
response.json(submittedPost);
also with templating engines you can render templates with server side variables and you can access them inside your templates like
app.get('/mypage', function (req, res) {
res.render('mytemplate_page',{template_variable:some_variable});
});
and you can use template_variable inside the template for looping through or displaying.