Creating routes for Ajax calls in NodeJs - javascript

let's say I have this route for my rendered HTML:
app.get('/profile/:id', function (req, res) { // my route
res.render('profile', { id: Number(req.params.id) }); // render the file and set a variable
});
and in my client side javascript file for the profile page I want to get data from the server. I request the data when loading the page by sending a user id to the server and the server returns a user object:
$(document).ready(function() {
var user = null;
$.ajax({
type: 'GET',
url: '', // This one is missing here
dataType: 'json'
}).done(function(data){
user = JSON.stringify(data);
});
console.log(user.name);
});
And my server would handle this function:
app.get('', function (req, res) { // missing route
var userId = ; // This is missing
var userObj = getUserById(userId);
res.send(userObj);
});
What route do I have to use? Tutorials say I have to pass in the route like /profile/:id but this route already exists?
I tried defining a new route like:
app.get('/reqUser/:id', function (req, res) { // Ajax route
res.send(getUserById(Number(req.params.id)));
});
and for my Ajax call I pass in the url http://localhost:8888/reqUser/12345 but this seems to be wrong because user is still null after using the Ajax call.
So how can I define a route handling the page and the Ajax call?

Edit: First off, you'll want to fix the bug in your client-side JS, where you are attempting to print user.name before user has been fetched from the server. You can fix this by moving your console.log statement into the done() callback like so:
$(document).ready(function() {
var user = null;
$.ajax({
type: 'GET',
url: '', // This one is missing here
dataType: 'json'
}).done(function(data){
user = JSON.stringify(data);
console.log(user.name); // log here
});
});
Regarding your routes question, you have several options. Below are two common solutions to this problem:
Create a separate api route to distinguish your API requests from your page requests. For example, app.get('/api/profile/:id, (req, res) => {...});'
Add a URL parameter to your AJAX calls specifying the format you want the response to be in, with the default being the page's HTML. For example, your AJAX would send a GET request to the URL /profile/2012?format=json, which would return the profile's information in JSON.
Personally, I prefer the first option, as it makes intent more clear.

Related

Request Still Attaches Cookie After Deleting it From Both Client and Server Side

I'm trying to implement a quick Login-Logout solution.
Login:
Sends a POST request with AJAX (Client-Side)
NodeJS creates a cookie (Server-Side)
Reloads the page with javascript (Client-Side)
Works fine
Logout:
Sends a POST request with AJAX (Client-Side)
NodeJS deletes the cookie (Server-Side)
I make sure to delete the cookie on client side as well with JS (Client-Side)
Reloades the page with JS (Client-Side)
NodeJS still somehow receives the cookie from the req ???
So, when I reload the page after Logout operation, I'm still logged-in. Only after I force refresh or press "Logout" one extra time, I see that I'm indeed logged-out.
I tried many different approaches and methods of loading the page and deleting the cookie, but nothing seems to work.
Javascript:
$("#logout").click(function () {
var username = this.value;
logout(username)
var currentUrl = window.location.href;
window.location.assign(currentUrl); //I tried different methods of reloading the page
});
// perform logout action
function logout(username) {
$.ajax({
type: "POST",
url: "/logout",
data: JSON.stringify({ username: username }),
success: function () {
//just in case remove the cookie
removeLoginCookie()
},
error: function () {
removeLoginCookie()
},
dataType: "json",
contentType: "application/json"
});
}
NodeJS:
app.post('/logout', (req, res) => {
try{
res.clearCookie('userlogin', { path: '/' })
res.send({ "status": "Logged out successfully!" })
}catch(e){
res.sendStatus(500);
}
});
I was able to fix the problem, by setting a timeout before reloading the page, but I'm not a fan of this solution and I'm still curious on why was it happening, and what would be a better way to do this.
$("#login").click(function () {
var username = this.value;
logout(username)
setTimeout(()=>{
var currentUrl = window.location.href;
window.location.assign(currentUrl);
}, 500)
});

Routing Express and outputting to template

lets say I have
router.get('/read', function(request, response) {
res.send({"result": "Success sent from routes/index.js."});
});
how do I output a template with the data. If I use res.send() I can't use res.render() right?
If my users are at /read and click a button to send some data with ajax I want to display that data in another template on /read
Edit: One way to get around this is to make a string when you return the data (or maybe not)
success : function(data){
$(".fillIn").html("<p style = 'color:green;'>" + data + "</p>")
}
I don't want a string.
The pic shows that on one page "/" there are 2 buttons and by clicking each button you can send data and that data can be displayed on the right depending on which button was clicked, a form with some data filled in or a table filled in with some data. I use ajax to send the data on click..There will be different forms with different styles. That's why I want to add in a template. I could do that with HTML using .load() I think but I cant figure out how do with that jade.
Here's my other Question
In your index.js file, use the following to capture GET and POST requests and render different responses:
app.get('/read', function(req, res, next){
res.render('emptyFormTemplate');
});
app.post('/read', function(req, res, next){
res.render('dataTableTemplate', {
name: req.body.name,
email: req.body.email
});
});
On the client-side, you you can something like this to POST the data to /read. You would include this script in emptyFormTemplate in the above example.
$('#myForm').submit(function(event){
var formData = {
'name' : $('input[name=name]').val(),
'email' : $('input[name=email]').val()
};
$.ajax({
type: 'POST',
url: '/read',
data: formData,
dataType: 'json'
});
});

jQuery + node.js express POST request

I'm trying to send a post request to a node server.
This is my client-side code:
function send(userid,message){
$.ajax({
method: "POST",
url: "/chat/messages?id="+userid+'&message='+message
})
clear();
}
This is my server side code:
app.post('/chat/messages',function (req,res){
var query = url.parse(req.url,true).query
insertMessage(query.id,query.message)
})
This works, however I'm not sure getting data in the query string using post is the right way to go.
I tried adding a data field in $ajax parameter:
function send(userid,message){
$.ajax({
method: "POST",
url: "/chat/messages"
data : {'id' : userid, 'message' : message}
})
clear();
}
And using bodyParser() in the server end to parse the body contents:
app.use(bodyParser.json())
app.post('/chat/messages',function (req,res){
console.log(req.body)
})
but when I log the response, the body{ } object is always empty.
Why is that?
Is a <form> tag necessary for POST requests?
I tried editing my ajax request to use json as the dataType and stringifying the data, but the req.body is still empty.
$.ajax({
method: "POST",
url: "/chat/messages",
data : JSON.stringify({'id' : userid, 'message' : message}),
dataType: 'json',
})
When you post data to a server, the data is usually urlencoded and added to the body of the request. In your example, it would look like this:
id=<userid>&message=<message>
Therefore, the bodyparser you need to be able to parse that is bodyparser.urlencoded()
app.use(bodyParser.urlencoded())
Note that it isn't always urlencoded, it all depends on what you are using to send the post. AngularJS for example defaults to sending it as json instead. The good news is you could simply add both bodyparsers and your route won't need to know which method was used since in both cases the data would end up on req.body with key/value pairs.
You should read the express documentation. http://expressjs.com/api.html#req
// For regular html form data
app.use(bodyParser.urlencoded())
app.post('/chat/messages',function (req,res){
console.log(req.body);
console.log(req.query.id);
console.log(req.query.messages);
})
You can also do req.params
app.post('/chat/messages/:id',function (req,res){
console.log(req.body);
console.log(req.query);
console.log(req.params.id)
})

Ajax Request in Node - Avoid Page Reload

I have an ajax request being called on form submit. The idea is to save a user's account information without a page reload, and give them a handy flash message to let them know the save was successful. I have no problem saving the data, but I do have a problem with avoiding a redirect on the POST (to a white page with the response data). Here's what I have:
In my Jade view
$("form").on("submit", function (e) {
e.preventDefault(); // prevent page reload
$ajax({
type: "POST",
url: '/account',
data: $("#accountForm").serialize(),
success: function() {
// can req.flash even be used here? How might it be?
req.flash('info', {msg: 'Your profile has been updated!'});
}
}
}
In my controller
exports.postAccount = function(req, res, next) {
var userData = req.body;
userData.id = req.user.user_id;
var updateUserCallback = function(err) {
// This is where everything falls apart
// Theoretically this should run the success handler in the ajax response
res.json(true);
// Any response I send changes the view to a white page with the data, e.g.
// res.send(anyData);
// Flash also doesn't seem to work, which seems weird...
req.flash('info', {msg: 'Your profile has been updated!'});
}
// Successfully saves the data, no problems here
UserModel.updateUser(userData, updateUserCallback);
};
Normally in the updateUserCallback I would just render the account view, but that defeats the purpose of ajax. I want to save the user's data without a page reload/redirect, while letting them know that the ajax function completed successfully (or didn't) via req.flash (flash module).
Basically any res.send() or res.json() call puts that data into a plain white page (no view). I suppose that I'm fundamentally misunderstanding how ajax works, but I've followed other examples for jQuery ajax calls in Node and have not been able to avoid the 'white page' problem.
Node:
var updateUserCallback = function(err) {
return res.send({
message: "Your profile has been updated"
});
}
Client-side JS:
success: function(response) {
// can req.flash even be used here? How might it be?
// Nope
//req.flash('info', {msg: 'Your profile has been updated!'});
$('#someModal').show().html(response.message); // just a sample implementation
}
Instead of using the form submit, you can use simple button click so that page will not get reloaded.

Trouble sending AJAX GET request to mongodb

I am currently trying to display data from a mongodb collection on the browser using nodejs and express and am having a very tough time with it. Here is the call itself on the clientside.
document.onload= $(function (e) {
var i = 0;
$.ajax({
type: "GET",
url: "http://localhost:3000/viewdata",
dataType: "jsonp",
jsonp: 'jsonp',
success: function (responseData, status) {
//code doing things with the data
}
Here is whats going on in node.
app.post('/viewdata', function(req, res){
tweets.find({}, function (err, doc) {
res.render('../../views/view.html', doc);
});
});
The call is returning "200 OK". I was able to view the data from mongo on the console so I know the data is there, I am not sure how to get to it and display it on the browser though. Thanks for the help
For anyone looking for the answer to this question, the problem is that I am trying to get data from the server in a post request. I made a separate GET request below the POST request and sent the data to the view. You can now use an ajax get request and use the data on the client-side.
app.get('/viewdata', function(req, res){
tweets.find().toArray(function(err, items) {
/*console.log(items);*/
res.send(items);
});
});
And on the clientside:
$.get("/viewdata", function(data) {
/*do stuff with the data*/
}

Categories