I have a nodeJS server using Express. It uses a pug template. It displays a bunch of images. I want it to display a button on each image. When that button is pressed, the server deletes the image and the client refreshes.
here is what I have so far for the .pug:
// register form
block content
form(name="getomdb",method='post')
div.input
input(type="submit",name="delete", value="Delete " + link[0])
div.container
h3#title
p#plot
link[0] references the image I want to delete. As far as I can tell, what this is doing is sending a POST request to my server with the value "Delete " + link[0].
My server attempts to handle it:
app.post('/', function(req, res){
console.dir(req.body);
console.log('post got');
res.render('index.pug', { links: links})
});
Apparently, there is no body to the request (it prints undefined). How I access which specific link it is trying to delete?
You should be able to access your value through
req.body.delete
Just add the name of the value you are passing in. Keep in mind if you ever start passing in json or other formats, you'll need to check out the "BodyParser" module.
app.post('/', function(req, res){
console.dir(req.body.delete); //add the .delete
console.log('post got');
res.render('index.pug', { links: links})
});
Related
Hi I can connect to and store to mongodb using mlab but I can't get the data in the form to remain on refresh.
The form takes in user input from input-boxes.
Any help would be great.
Thanks
If being able to get the same form data for all the requests (no matter where they are made from)is what you want, then a possible workaround could be as follows:
1) Store the initial form data(probably empty) in the database, get the ObjectId and hard code it in your code, this way all the updates would be made to that specific MongoDB document only.
2) The form route (below one) should do nothing except for serving the file which has the form
app.get('/form1', function (req, res) {
res.sendFile(__dirname + '/public');
//record.find({"_id": ObjectId("MLAB ID")})......dont do this
});
3) There should be another route that sends form data
app.get('/getdata', function(req, res) {
record.find({"_id": ObjectId("MLAB ID")}, function(err, doc) {
res.send(doc)
})
});
4)The static file that you send to the client should have a javascript function such that it asks for the form data as soon as your window loads and then sets the value of input elements from that data recieved:
window.onload = function() {
//make a GET request to /getdata to get form data....store it in obj
//then set the input values
document.getElementById("yourchoice").value = obj.yourchoice;
//and set the value of other input fields ....in similar amnner
}
5) The POST request you make should update that specific document( findOneAndUpdate?? )
Disadvantage of this method:
For one operation we request a file from server and then another request to get form data, so two requests for one operation, since we cannot use both res.sendFile() and res.json() together...one way to get around this is to hide the form data as well in the HTML document using a template engine. More about this can easily be found. Anyways the above method does solve your purpose.
I hope I correctly understood the problem statement.
Happy coding!!
Edit:Although the above mentioned points are explainatory, I have written a sample snippet at : https://pastebin.com/AvgVyx7b
It works perfectly fine
I have a nodeJS application which takes user information from a form and saves to a mongoDB database using mongoose.
example:
router.post('/', (req, res) => {
newUser.save()
}
I've seen other websites which updates the url after the form is submitted with what I guess is a query string of the user and adds to the end of the url.
Example: http://stackoverflow.com/profile/Jon%Doe
Not sure how to update a url with user information after the form was submitted.
I tried to render a file:
router.req('/', (req, res) => {
res.render('profile' + username) //username is a variable of the user
}
but that only looks for a url with a username. Thinking I have to update the ejs template files with the username somehow.
To change the URL after a form post, you would use res.redirect() to redirect the browser to a new URL. The browser will then request that new url and you would need to have a route for that new URL in order to return the desired page content.
router.post('/', (req, res) => {
// other code here to process form data
newUser.save(..., function(err) {
if (err) {
console.log(err);
res.sendStatus(500);
} else {
// build new URL here
res.redirect(newURL);
}
});
}
If you then want to display the username in the page that you redirect to, you would use an EJS template that has a place in it for the user name and you would fetch the username from wherever you put it in the URL and feed that to the res.render() for the template so that EJS would insert the user name in the proper place.
If you're doing some kind of login, then you may want to do the whole process differently. You may want to create a user session object (probably with express-session) on the server and keep the username in there so then anytime you want to render a page, the username can be fetched from the server-side session object rather than putting it in the URL. This is probably a bit more foolproof.
I'm using Node/Express and Jade to build and App.
I have a POST route that sanitize and validate form input and then save this to a MongoDB.
If this form input is'nt validated, the route will throw and error and the error handler will re-render this same page...
And here come the problem. In this re-render and want the form values be pre written and ready to be corrected by the user... I don't want a clean form where the user has to re-write everything.
I have tried to submit the req.body (sanitized) data to the re-rendered page, which works.
But if try to use this data in my Jade view, Node will output and error when this req.body data is not defined... Like when you enter this page for the first time, and have'nt entered any wrong inputs yet.
How do i solve this in a good way?
edit - Without a code sample I'm not sure if my example is more or less than you need.
If you render the form template immediately within the the form's POST request handler, you probably don't need to involve req.session. Just save the appropriate locals and render your template.
If you must redirect or otherwise need to have the values available across multiple requests, you can save them in req.session as shown below.
Either way make sure your Jade template handles all cases; in my example I test if(locals.savedValues) to decide whether to write defaults or saved values into the form.
Finally if the error is not jade related please paste that error.
Use req.session to save the values. Set up a locals variable to represent the saved values or null before you render the form.
app.get('/form', function(req, res){
res.locals.savedValues = req.session.savedValues || null;
res.locals.savedErr = req.session.savedErr || null;
res.render('form');
});
app.post('/form', function(req, res){
var values = {
name: req.body.name,
email: req.body.email,
};
validateForm(values, function(err, processed){
if(err){
req.session.savedValues = processed;
req.session.savedErr = err;
// req.session.savedValues = values, if you dont want to propose changes
res.redirect('back');
} else {
delete req.session.savedValues;
delete req.session.savedErr;
res.redirect('/success');
};
});
});
In your jade template, handle both cases:
if(locals.savedErr)
span.error=locals.savedErr
form(action='form', method='post')
if(locals.savedValues)
input#name(type='text')=locals.savedValues.name
input#email(type='text')=locals.savedValues.email
else
input#name(type='text')
input#email(type='text')
Currently a user comes to my register page with an invitation ID
Example: http://www.mysite.com/user/register/50e203eb4d37bdfd22000042
The page loads and the form loads etc.... all is great. I then do some back end validation and if validation fails I call the res.render with the messages and the form data:
res.render('user/register', {
messages: messages
, form: form
});
It all works as expected however when the render occurs it puts the user back to:
http://www.mysite.com/user/register (its missing the invite_id)
How can I pass along a URL param with the res render?
If I do:
res.render('user/register/50e203eb4d37bdfd22000042', {
messages: messages
, form: form
});
Its actually looking for that 50e203.... file and giving me the 404 not found
Thanks!
Are you perhaps confusing res.render() with app.get()? It looks like you're trying to specify a route in that second example: res.render('user/register/50e203eb4d37bdfd22000042'... - but res.render doesn't specify routes, you need app[METHOD] for that, where app is an express instance.
In order to handle a GET request to /user/register/someinvite, use:
app.get('/user/register/:invitation', function(req, res, next) {
// in here you can access the invitation id with req.params.invitation
res.render('user/register');
});
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.