submitting form data without leaving page. Express, Node.js, Pug - node.js

I read through a similiar post but the individual was using perl and something elss so it didn't help me. My question is how can i submit a form with node js/pug but remain on the same page.
In the pug form the method is set to POST and action set to /profile
in my nodejs i'm using
router.post("/profile", req, res, next){
return res.redirect("back")
}
The problem is that all this does is reload the page. I want to stay on the page and simple show a message saying "profile update".

Then don't return a redirect. Simply take the post data and process it, you can return the state of the operation, for example. Then however you should use an AJAX query instead of stock form, which will always redirect you to the action URL.
router.post("/profile", req, res, next){
return updateProfile(req.body); // true or false
}
And in jQuery, for example, you can perform an AJAX request
$.ajax({
type: "POST",
url: "/profile",
data: profile_form_data_object,
success: function(data) {
alert("Result of the profile update was: " + data);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Node, Express, Ajax, Form Submission

Help, I'm Stuck! I am playing with a CRUD setup with Node Express but with AJAX post request. I have the read form working fine.
The form has one input filed which is a lookup email. AJAX post the form data with the following code
if ($("#rsvp-search-form").length) {
$("#rsvp-search-form").validate({
rules: {
...
},
messages: {
...
},
submitHandler: function (form) {
$("#loader").css("display", "inline-block");
$.ajax({
type: "POST",
url: "/",
data: $(form).serialize(),
success: function (data, textStatus, jqXHR){
if (typeof data.redirect == 'string')
window.location = data.redirect;
}
,
error: function() {
$( "#loader").hide();
$( "#error").slideDown( "slow" );
setTimeout(function() {
$( "#error").slideUp( "slow" );
}, 5000);
}
});
return false; // required to block normal submit since you used ajax
}
});
}
I have a express post route to '/' that returns a status with res.status(#).send() and the proper success/error block is executed based on the whether status # is 400 or 200.
Now on the update form I have the same basic setup with many more form inputs, but the AJAX code does not process the res.status(#).send() response by executing the proper success or error block, instead it is just loading a new page with the same url as the request was processed from.
The AJAX code request is similar to the top with difference of url:
submitHandler: function (form) {
$("#loader").css("display", "inline-block");
$.ajax({
type: "POST",
//The website when loaded has an invitation
//object that is passed by express
url: "/rsvp/" +invitation._id,
data: $(form).serialize(),
dataType: 'application/json'
I verified that the proper post route is running and receiving the invitation._id. It returns res.staus(#).send() but the ajax does not process the success or error block it just redirects to the requesting url but does not actually render the url.
I don't know if it is just that the form is still processing the default action, if the response from express is not correct, etc etc
I hope I have been clear on my issue and someone knows what I am doing wrong here.
Regards!
Update!
I got it working. Though the url with variable was correct and express was receiving the proper id, JS was throwing an error causing everything to crash. I never caught the error because the page would reload to the blank page and clear the console. I fixed it by saving the id in a hidden field when rendering the form and used that instead. Seems to have fixed the problem.
Thanks for looking!

Setting Session After Setting Headers

I'm trying to implement an asynchronous method which makes a POST call to a certain API and retrieves its data, and then stores the result in the user's session. The task itself seems to be quite easy, but it gets problematic when I do it the 'fire-and-forget' style.
I do not wish to wait for the result to come back from the external API, but instead let the user load his requested page and continue browsing. Only when the response is ready, I want it saved in the session.
Everything seems to be working fine, but the only problem is the moment I set the session and proceed to the next route, everything gets lost as if I never set it in the first page. Debugging the code also shows that the process completes without any errors whatsoever, therefore I suspect an issue with setting the session after the response headers are already set. Can't seem to understand why that should be an issue, though.
I am using nodejs with express, and mongodb for session & database handling.
router.get('/myroute', function(req, res, next) {
request({
url: endpoint,
method: "POST",
json: true,
body: jsonData
}, function(error, response, body) {
req.session.mykey = 'some response';
});
res.redirect('/otherroute');
});
router.get('/checkresult', function(req, res, next) {
res.json(req.session.mykey);
});
I think you'll need to explicitly call save.
function(error, response, body) {
req.session.mykey = 'some response';
req.session.save();
}
https://expressjs.com/en/resources/middleware/session.html#sessionsavecallback
This method is automatically called at the end of the HTTP response if the session data has been altered
In your case this automatic save will be occurring too soon.

Direct linking to route (e.g., /articles/:articleid) returns plain JSON, skips AngularJS and DOM

I have a multipage blog based on https://github.com/linnovate/mean.
Right now when I go directly to a /articles/:articleid type url, all that I see is plain JSON ({"title":"this is the title","_id":"12345","user":"me"}) returned from my database. If I go to /articles/:articleid from my main page / -> clicking a link, the page parses fine since Angular and the DOM have already loaded from being at the main page, so Angular reads and parses the JSON that's returned.
Ideally, I want to be able to enter a direct URL to an article (e.g., /articles/:articleid) and have the server load the DOM and then have AngularJS return and parse the JSON. Or have some way for my server to load the html/css/etc. if it hasn't been already, before parsing the JSON (and thus avoiding plain json outputs).
Node routes:
var articles = require('../app/controllers/articles');
app.get('/articles', articles.all);
app.get('/articles/:articleId', articles.show);
app.param('articleId', articles.article); //This is called when I directly link to an article
Articles model code:
exports.article = function(req, res, next, id) {
Article.load(id, function(err, article) {
if (err) return next(err);
if (!article) return next(new Error('Failed to load article ' + id));
console.log(req.headers['x-requested-with']);
if ( req.headers["x-requested-with"] === "XMLHttpRequest" ) {
console.log('sending jsonp' + req.article.title);
res.jsonp(req.article);
} else {
console.log("sending page");
res.render('index', { //my default JADE skeleton page
user: req.user ? JSON.stringify(req.user) : "null"
});
}
//req.article = article;
next();
});
};
exports.show = function(req, res) {
console.log(req.headers['x-requested-with']);
if ( req.headers["x-requested-with"] === "XMLHttpRequest" ) {
res.jsonp(req.article);
} else {
res.render('index', { //default page
user: req.user ? JSON.stringify(req.user) : "null"
});
}
};
Angular route:
when('/articles/:articleId', {
templateUrl: 'views/articles/view.html'
}).
The controller that handles the individual article is:
$scope.findOne = function() {
Articles.get({
articleId: $routeParams.articleId
}, function(article) {
$scope.article = article;
});
//$scope.htmlReady();
};
Thanks in advance!
EDIT:
I did some checking for the content type in the headers. I'm now able to discern whether it's a direct link or if it's coming from another page in the app, but I don't know how both render the template page (jade), start Angular, and supply JSON to it all in one go if it's a direct link.
My folder structure:
public
-- css
-- img
-- js
-- lib
-- views
My log output when I direct link (it seems to be using /articles as a base):
GET /articles/72119103c2e3a932b51e000201 304 619ms
GET /articles/css/blogstyle.css 404 134ms
GET /articles/lib/angular-resource/angular-resource.js 404 126ms
GET /articles/lib/jquery/jquery.js 404 136ms
GET /articles/lib/angular/angular.js 404 134ms
GET /articles/lib/angular-cookies/angular-cookies.js 404 136ms
GET /articles/lib/bootstrap/js/bootstrap.js 404 148ms
GET /articles/lib/angular-bootstrap/ui-bootstrap-tpls.js 404 58ms
GET /articles/lib/angular-ui-utils/modules/route.js 404 67ms
You need to look at the request content-type and return the complete angular page when it is content/html and JSON when it is jsonp request. This is for the route /articles/:articleId, of course.

How to apply post redirect and get pattern in node.js?

I am testing with a very simple application in node.js where I create and save an application. I show the post form with the newPost function and I receive the post with the data in the savePost method. In the latter one I do a validation (with iform module) and I want to go show again the same page as before but filling the form with the data sent by the user and also with the errors found.
I have a similar code like this one. In it I render the same jade page if I find any error. It works though I want to apply the pattern redirect and get there as I don't want to send again the post request when the user presses F5.
So, how is the usual way to make a post redirect and get from the post method passing them all the parameters I have received adding the errors? Is there any module which can help to do so?
var prepareObject = function(req, res){
var errors = {};
if('iform' in req){
errors = req.iform.errors;
}
return {title: 'Nuevo Post', body:req.body, errors: errors};
};
// mapped as /newPost (type GET)
exports.newPost = function(req, res){
//show form to create post
res.render('newPost', prepareObject(req, res));
}
// mapped as /savePost (type POST)
exports.savePost = function(req, res){
if(req.iform.errors) {
//there are errors: show form again to correct errors
res.render('newPost', prepareObject(req, res));
}else{
//no errors: show posts
res.redirect('/posts');
}
}
You can redirect to GET "/newPost" instead of rendering the "newPost" template.
To have autocomplete working, you may either add the data to the redirect query (faster) and render it, or add the data to the session (don't forget to delete it after rendering), but the later option requires a session store.

Cant get view to render

I am developing an application with node.js, express, couchDB and using nano to communicate with couch.
I am using a jquery get request from client javascript. Using fiddler i can see that i get my view in the RAW result but the view is never rendered.
client:
$.get('employee/'+customerId, function(data){
return;
});
route:
app.get('/employee/:id', employee.viewEmployee);
viewEmployee:
exports.viewEmployee = function(req, res){
db.get(req.params['id'], { revs_info: false }, function(err, body, header) {
res.render('employee/single', {employee: body});
});
};
Everything works with no errors and i get the 'employee/single' view html in the raw response. my question is why the view is not rendered? why is the html just sent back in the raw and how can i get this to work?
Your $.get call is using a call back that isn't doing any thing.
from the jQuery api examples
$.get("test.php",
function(data){
$('body').append( "Name: " + data.name ) // John
.append( "Time: " + data.time ); // 2pm
}, "json");
Shows you how to do this.
You are doing an ajax call.
try console.log(data) inside your $.get callback, are you seeing the html you expect?

Resources