Submitting a form from email ejs template and use the value in a middleware - node.js

I am sending an ejs email along some parameters (userId and email). Inside the email there is a form that should send this (userId) variable back to the server and should be used in a middleware. However, nodejs does not recognise the req.body...
The ejs form have an input with the value populated to be the userId and should be passed down to the action url...:
<form action="http://localhost:3000/api/allowUser" method="POST">
<!-- Here i passed the userId as a value and send to email-->
<input type="text" id="userId" name="userId" value="<%- userId %>">
<input type="submit" value="Allow user" />
</form>
This is the email received with the input value.
Outcome:
Now, the administrator is redirected to the success page by accessing the /allowUser endpoint. Here, I need to use the req.body.userId, but is undefined... I cannot have access even to req object...
exports.allowUser = async (req, res, next) => {
// NEED TO USE THE userId HERE
let {userId} = req.body; //Undefined
console.log(req.body); //empty object
res.render('success.ejs', {userId: userId});
}
The redirect function works, but the userId cannot be passed or used in the allowUser function.
However, if accessing the network tab in the success page I can see there the userId being present at every refresh. But still not being able to access the variable
anyone have any ideas please? Many thanks, Daniel

Hello i can see that your ejs form is correct,but in your req.body you should get userid like this way
let user_id=req.body.userId //userId name
// from ejs form
Then render success page
res.render("success",{userid:user_id});
//without .ejs in success page
Also i think your form action doesn't need the whole link,only the endpoint /allowuser
Make sure that your routes are correct,hope this will help you.Tell me again if problem still exists.

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.

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

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

Express JS does not perform delete

PUGJS script
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
My ExpressJS code
router.post('/delete', function(req, res, next) {
var id = req.params("i");
console.log("i am 0")
MongoClient.connect(url, function(err, db) {
console.log("i am 1")
db.collection('books', function(err, book) {
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
console.log("i am 2")
if (err) {
throw err;
} else {
db.close();
res.redirect('/');
}
});
});
});
Trying to perform a delete request but it does not even print ("i am 0")
can not determine what's broken with the code
NPM response POST /delete 404 7.247 ms - 1202
When you see a 404 the root cause is definitely how you set up the routing. This code would be successfully called if it is in app.js/server.js (or whatever your root express file is), but a 404 means that you have placed it in a secondary file and are using another path in there somewhere.
With that said, you also have an issue with how your route is defined if you want to read a route parameter (which is what the first line of your route handler tries to do).
router.post('/delete/:i', function...
The form itself isn't passing any id though through name (or id). You could either pass the id through the url called:
action= "/delete?id=" + id
...and read this in your route handler using req.query.id or you could insert a hidden input in the form and read it using req.body.id.
Also, the form name attribute has been deprecated and should be replaced with id.
Then, it's important to note that pug is highly dependent on indentation. Your code as pasted will generate an empty form and a separate input field.
This:
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
Generates this HTML:
<form id="form1" action="/delete" method="POST"></form>
<input type="submit" name="itemId" value="delete">
If you change the pug template to this (note the two additional spaces on the input line):
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
You will get this, which should work as expected:
<form id="form1" action="/delete" method="POST">
<input type="submit" name="itemId" value="delete">
</form>
Then, there's the problem in your delete function where you're missing a callback.
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
You need to either add a promise or callback here otherwise your code will move straight to close the connection.

NodeJS Post request using a Button

I don't know if this is possible or not. All the research I've done has shown that it is possible with a form and text input. But anyways, Using NodeJs & Express I want to be able to click a button on my webpage, and once it's clicked, it sends a post request to my Node.JS server.
Simpler way of saying it:
When button is clicked, send info to the server.
Goal I'm trying to achieve:
When button is clicked, it sends some sort of ID/code/anything to turn on a service from my database. (I have yet to learn how db's work so I am just trying to focus on front end.)
Code I have so far:
app.post("/send", function(req, res){
var newID = req.body.ID;
res.redirect("/action")
});
<form action="/send" method="POST">
<input type="button" name="newID" placeholder="Button">
<button>send</button>
</form>
You do not need to use jQuery or AJAX.
Simply add an input of type submit inside the form tag so that the POST request defined by your form tag is submitted.
Your newID input should be of type text, this allows entering a value in the input field.
The newID value can be retrieved server side with req.body.newID (be sure to use the body-parser middleware).
<form action="/send" method="POST">
<input type="text" name="newID" placeholder="Enter your ID"/>
<input type="submit" value="Click here to submit the form"/>
</form>
For this purposes you should use $.ajax,
example:
$('button').on('click', function() {
$.ajax({
type: 'POST',
url: '/send',
data: { ID: 'someid' },
success: function(resultData) {
alert(resultData);
}
});
});

express.js - req.body?

I'm new to js,
I see this a lot in the code I'm reading
_.pick(req.body, ' ' , ' ')
What does req.body do?
And when can I say req.body.something?
req.body holds parameters that are sent up from the client as part of a POST request. See the API.
// POST user[name]=tobi&user[email]=tobi#learnboost.com
req.body.user.name
// => "tobi"
req.body.user.email
// => "tobi#learnboost.com"
// POST { "name": "tobi" }
req.body.name
// => "tobi"
(req.body, ' ' , ' ') --> here req is the parameter of your function and using this parameter your can access the properties over then url.
so look this example
suppose this is form
<form>
enter the name : <input type="text" name="name">
<button type ="submit"> submit </button>
</form>
so if you want to access the name -- which is filled by the user end.
so for this you can
do like this-> console.log(req.body.name); -- this will print the name (property) in console.

Resources