Make data persist in form using mongodb node express - node.js

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

Related

NodeJS and Express - How to store data in Array and not render in a web browser DOM?

I have a route in node - express and it is working properly - getting data from a database.
app.get('/getdata/:key', function(req, res){
console.log("Search key(s):", req.originalUrl.split("/")[2]);
keys = req.originalUrl.split("/")[2]
Keys = keys
arr = keys.split(",");
client.mget(arr, function (err, Values) {
res.send({ Keys, Values});
});
});
But I do not want to display all data (records) into the browser screen (DOM) - just want to get it as array and parse it later with some JavaScript in a browser.
How to achieve that?
If you are sending all data at once, so the client will not do another request. You must filter the data at the client's side.
As it is probably an array of objects, you could use .filter function.
Here you have some info about how to do the filtering: w3chools - JavaScript Array filter() Method
As #jfreind00 recommended - return it as JSON.
Perform a GET request with JS in your Front-end:
http.get('/getdata/${key}', (err, res) => {
// do something with your data here
}
Depending on your used frameworks this code could differ.

iterative render with node and express

New to node and async and still struggling with concepts.
Trying to use express/handlebars render with a callback to iteratively build an html body with content from an array. End goal is to send a response with a number of emails each one individually rendered using a view.hbs.
Got this far but realised it was never going to work. res.render can't pass my html variable back in the callback and res.send would run before the renders have completed???
function buildRes (req, res, email) {
var html = '';
Object.keys(email).forEach(function (i) {
res.render('emailPanel', {subject: email[i].subject, body: email[i].body},
function(err, renOut) {
if err throw err;
html=html+renOut;
}
)
})
res.send(html);
}
Any suggestions on how I should be approaching this problem?
Started out trying to use handlebars #each helper to do the iteration but all of the examples show a simple list whereas in my case there a multiple array parameters to be passed to the render.
I'm still not sure what you're trying to accomplish with this, but one is for sure, I think it's better for you to do all looping inside your view by passing the entire array (filtered) with res.render to your view. Also note that you can respond only once per request.

How to pass selected data from database to view file in Node js?

I am trying to pass selected data from database in Node Js. But i could not able to pass the data to view. Is there any proper way to pass data and display into view in Node Js.
try
app.get('/',function(req, res){
var data = fetchFromDataBase();
res.render('viewName',{data: data});
});
in viewName (assuming data is string) do
block content
p content is #{data}
hope it helps :)
Alternative Solution:
You can pass the data by setting on res.locals to the view as below:
function(req,res,next){
res.locals = {
data : fetchDataFromDatabase() // some function
};
res.render('view');
}
in view you can access it directly using:
data
e.g. in Jade:
html
head
title helloWorld
body
h1 #{data}
Explain:
This object contains response local variables scoped to the request, and therefore available only to the view(s) rendered during that request / response cycle (if any).
res.locals is an object passed to whatever rendering engine your app is using (in this case jade). It is 'global' in the render, so you don't need to prepend anything on to them to use them.

JadeJS and pre written form values at re-rendering views

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')

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.

Resources