req.body value undefined for form field value set by javascript function - node.js

I am building a node.js,express.js and passport.js app. Once logged into the profile I ask the user to click a button “Get Location” to get the users location.
Profile.ejs
<form action="/testform" method="post" >
<div class="form-group">
<input type="text" class="form-control" id="latVal" placeholder="latitude">
<input type="text" class="form-control" id="longVal" placeholder="longitude">
</div>
<button type = "submit" class="btn btn-warning btn-sm">Save</button>
</form>
<button type = "submit" class="btn btn-warning btn-sm" onclick="getLocation()">Get Location</button>
onclick the getLocation() function is called which is located in mapCall.js
function getLocation()
…
//call to showLocation()
}
function showLocation(position) {
…
document.getElementById("latVal").value = latitude;
document.getElementById("longVal").value = longitude;
}
showLocation() sets the values in the form to the latitude (id="latVal") and longitude (id="longVal") returned from the API call. The values appear in the form field. From here I want to save these values to the users profile data in MongoDB which I try to achieve in routes.js by click of the “Save” button which triggers the function below
app.post('/testform', isLoggedIn, function(req, res) {
user.findById(req.user.id, function(err,user) {
if(!user) {
req.flash('error', 'No accound found');
return res.redirect('/profile');
}
user.location.latitude = req.body.latVal;
user.location.longitude = req.body.longVal;
user.save(function(err){
res.redirect('/profile');
});
});
});
When I console.log req.body.latVal and req.body.longVal the value for these variables is undefined. Nothing is saved in the db.
In server.js I have
var bodyParser = require('body-parser');
app.use(bodyParser());
Upon looking into proposed solutions to req.body returning undefined I tried
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
I didn’t think adding the two lines above would work because the value returned by the API is not in JSON format. This did not work. I checked the typeof for latitude and longitude and it is a number. I am not sure why req.body is not picking up the value.
My initial guess was that app.post tries to read the value before the API can return a value in which case req.body.latVal would read an empty field. I added the save button to test that theory which also proved wrong.
The closest thing I found to my issue is this which was never resolved.
Any guidance is highly appreciated or perhaps even a better way to accomplish this will be great. The reason I have the form fields populate is because I couldn't think of another way to send the values from the frontend to the backend for saving.

Add the name attribute to your inputs.
<input type="text" class="form-control" id="latVal" placeholder="latitude" name="latVal">
<input type="text" class="form-control" id="longVal" placeholder="longitude" name="longVal">
EDIT: (from the comment)
You can do an AJAX call to your server after the getLocation() call.
function getLocation() {
///you get the lat and long
showLocation(position)
saveLocation(latitude, longitude)
.then(function(resp){
//do something with resp
})
}
function saveLocation(latitude, longitude) {
//we have native fetch in newer browsers, so
return fetch("/testform", {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8", //if this doesn't work use the below one
// "Content-Type": "application/x-www-form-urlencoded",
},
body: JSON.stringify({latitude,longitude}), // body data type must match "Content-Type" header
})
.then(response => response.json());
}
This is just an outline of what you can do. Extend this code to your needs.

You are correct in most parts ,You just have to replace ID with name.that is the only way nodejs will be able to locate to your input field

Related

How to store and retrieve checkbox state on refresh of page? Mongoose/EJS/Nodejs/Express

I have a checkbox, essentially like a to do list. When i check the box, I want to retain the state even after i refresh the page by using mongoose. I do know of localstorage, however EJS runs on a server side. Currently I am able to post the checkbox to my express side.
IN EJS
form id="form2" action="/check" method="post"></form>
<input form="form2" type="checkbox" name="checkboxx" onChange="this.form.submit()">
IN EXPRESS
app.post("/check", function(req,res){
Item.updateOne({checked: req.body.checkboxx.checked}, function(err){
if(err){
console.log(err);
} else console.log("successfully updated db")
})
res.redirect("/")
})
My collection is "Item", the schema includes a boolean property "checked"
checkboxx is the name of the input checkbox.
Any way to update the information of the checkbox state and reload the saved states upon refreshing the page?
In my case, the user profile page is also a form for data entry. (I save the form values with mongoose on a Mongo Atlas db, so some steps are skipped here.)
In my profile.ejs page, the toggleswitch is :
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="onOffSwitch" id="onOffSwitch" <%= params.onOffSwitch ? "checked" : "" %> >
<label class="custom-control-label" for="onOffSwitch">Activate</label>
</div>
And in my Express app the route is :
app.post(`/api/params`, isLoggedIn, (req, res) => {
const email = req.user.email;
const onOffSwitch =req.body.onOffSwitch;
});
res.redirect(`/profile`);
});
Even after a log out and re-login, the checkbox value gets releaded correctly.

how make checkbox stay checked and reset in node js

I am working on a small project with checkbox and node js. I need the checked box stay on the screen after I click submit button and reset the form after clicking reset button.How can do that?
ejs code
<form method="post" action="/">
<input type="checkbox" name="preference" value="A">A
<input type="checkbox" name="preference" value="B">B
<input type="checkbox" name="preference" value="C">C
<input type="submit" value="Click to Submit">
<input type="reset" value="Erase and Restart">
</form>
node js
express.get('/', (req, res) => {
res.render('form');
});
express.post('/', (req, res) => {
console.log(req.body);
let checkedValue =req.body.preference;
let output = checkedValue==undefined?`You didn' make selection.`:`The preference iterm on menu is ${checkedValue}`;
res.render('form',{
output:output,
});
});
What's going on is that when you submit your form, the webpage is reloaded, so you lose your checked state. You can either save the values on your server and have them pre-checked using an optional checked flag in your ejs template or you can add some client side javascript to handle the form submission for you by writing and event handler for the submit event on the form.
if you expand your ejs template with a conditional checked value on your inputs, your returned page will have them pre-checked
<input type="checkbox" name="preference" <% if (submittedValue === "A") { %>checked<% } %> value="A">A
Or, here's a super simple bit of javascript that would send the values to your server
document.forms[0].addEventListener('submit', function (e) {
e.preventDefault(); // prevent the form from submitting with a page refresh
const data = { values: [] };
e.target.elements.forEach((formEl) => {
if (formEl.checked) data.values.push(formEl.value);
});
fetch('/urlToProcessYourForm', { method: 'POST', body: JSON.stringify(data) });
});

returning or looking up object from html input in node express

I have an html/handlebars form set up with a Node/Express backend. the form offers options populated from a database. I am able to get the form to return a single user selected value and save it to my mongodb, but I really need the whole object.
{{#each proxyObj}}
<p>
<label>
<input type="radio" name="proxyTitle" value="{{title}}"/>
<span>{{title}}</span>
</label>
</p>
{{/each}}
and this is the express:
router.post("/proxies/:id", ensureAuthenticated, (req, res) => {
Project.findOne({
_id: req.params.id
}).then(project => {
const newProxy = {
proxyTitle: req.body.proxyTitle
// I need the other object values to go here, or to be able to retrieve them later
};
// Add to proxy array on the Project object in the collection
project.proxies.push(newProxy);
project.save().then(project => {
res.redirect(`/projects/stakeholders/${project.id}`);
});
});
});
Is it more sensible to try to load in the entire object as a value in the input field, or to return the id of the object, and look it up in the db? I need to display some of the returned object information on the same page, and also to use it later. Which is more efficient, and what is the best way to achieve it?
If I'm getting it right, the problem is that you're trying to put multiple inputs with the same name on one form in <input type="radio" name="proxyTitle" value="{{title}}"/>, which gives you something like
<input type="radio" name="proxyTitle" value="Title 1"/>
<input type="radio" name="proxyTitle" value="Title 2"/>
<input type="radio" name="proxyTitle" value="Title 3"/>
As explained here, the browsers will chew it, but the server-side handling may require some adjustments.
In your case, the easiest fix would be to add index to the names of parameters. So, your form would be looking like this:
{{#each proxyObj}}
<p>
<label>
<input type="radio" name="proxies[{{#key}}]" value="{{this}}"/>
<span>{{this}}</span>
</label>
</p>
{{/each}}
(note that if proxyObj is an array, you would have to use #index instead of #key; also, depending on the proxyObj fields' structure, you may have to use this.title as the values to display and whatnot).
As for your server-side handling, you'll have to loop through the proxies you receive and handle them one by one, e.g.
router.post("/proxies/:id", ensureAuthenticated, (req, res) => {
Project.findOne({
_id: req.params.id
}).then(project => {
project.proxies = []; // this is only in case you wanna remove the old ones first
const proxies = req.body.proxies;
for(let i = 0; i < proxies.length; i++) {
// Add to proxy array on the Project object in the collection
project.proxies.push({ proxyTitle: proxies[i].title });
}
project.save().then(project => {
res.redirect(`/projects/stakeholders/${project.id}`);
});
});
});

Rendering data in handlebars using express framework

Hello I am working in Express Framework, I am using handlebars to render the data from my mysql table. While trying to render the data using below code,instead of rendering value it displaying [object object]. I posted my code below.
index.js:
var query = connection.query('SELECT * FROM requestor_auth WHERE question_id = ? AND answer = ? AND app_key = ? LIMIT 1', [data.qid, data.ansvalue, data.appid], function(err,rows)
{
if(err) {
console.log("Error Selecting : %s ",err );
res.redirect('/');
} else {
res.render('requestform',{page_title:"Edit Customers - Node.js",data:rows});
}
requestform.hbs:
<div class="addressto">
<h4>To,</h4>
<br>
<span style="font-size:18px;margin-left:10px;">The Collector Of</span>
<input type="text" value="{{data}}" class="line" class="text-line" style="margin-left:35px;"><br>
</div>
The value in the form input displaying as [object object]. I tried as data.key_value to render the data but it is not displaying the value.
Please give me a solution. Thank you.
Because the result of Mysql response is array so it should be:
var query = connection.query('SELECT * FROM requestor_auth WHERE question_id = ? AND answer = ? AND app_key = ? LIMIT 1', [data.qid, data.ansvalue, data.appid], function(err,rows) {
if(err) {
console.log("Error Selecting : %s ",err );
res.redirect('/');
} else {
res.render('requestform',{page_title:"Edit Customers - Node.js",data:rows[0]});
}
If there's a same error you should console.log() your result to check the value.
The rows argument in your callback function is by a select query always an array of objects. With handlebars you should be able to do the following:
<div class="addressto">
<h4>To,</h4>
<br>
<span style="font-size:18px;margin-left:10px;">The Collector Of</span>
<input type="text" value="{{data[0].answer}}" class="line text-line" style="margin-left:35px;">
<br>
</div>
Also multiple class names can be in one class attribute.

How to catch the object_id of a post submit in Node.js (MongoJS)?

I have this code in app.js where I insert the content of the title and content fields to their respective document fields in MongoDB:
//post to 'post/new'..
app.post('/post/new', function(req, res){
//get the `title` and `content` fields & save them as variables to be later reused (they rely on the `name:` values).
var title = req.body.title;
var content = req.body.content;
//call the database and find the `_id` to be used in the redirect later..
db.local.find({_id: ObjectId(req.params.id)}, function(id) {});
//insert the title and content in the database (taken from the submit form)
db.local.insert ( {title: title, content: content},
//not sure if I really need to define an err&doc right now so to be ignored..
function(err, doc) {
//redirect to "localhost.com/post/(post)_id/(post)title"
res.redirect('/post/'+req.params.id+'/'+req.body.title);
});
});
This is what I have on post_new.ejs:
<form method="post">
<div>
<div>
<span>Title :</span>
<input type="text" name="title" id="editPostTitle" />
</div>
<div>
<span>Content :</span>
<textarea name="content" rows="20" id="editPostBody"></textarea>
</div>
<div id='editPostSubmit'>
<input type="submit" value="Send" />
</div>
</div>
</form>
The problem is that I get all but no _id in the res.redirect to work, meaning, the title works wonderfully, but the _id no..
How can I get the object id to work in the redirect? Thank you!
EDIT
This is the problem I get and think it's unrelated..but I'll include it for the full view of the issue.
500 Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
Assuming you are using the native node MongoDB driver the callback of the insert function returns the array of inserted objects.
The example in those docs is a pretty good one. Adjusted for your example, it would like something like this:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
db.collection('local').insert({title: title, content: content}, function(err, docs) {
console.log('Inserted _id is '+docs[0]._id);
});
});
Regarding your error, it sounds like req.params.id is not a valid BSON ObjectId.

Resources