"Waiting for localhost" after form submission: node/express/react - node.js

I am working with node/express/react. I am using a form on the frontend to delete entries from the backend database:
<form id="delete" action="/delete" method="POST">
<p>First name:</p>
<input type="text" name="first" />
<p>Last Name:</p>
<input type="text" name="last" />
<input type="submit" value="delete person from database" />
</form>
The entry gets deleted from the backend database. But I get this message at the bottom of the browser window on the frontend:
Waiting for localhost...
Then after about a minute, I get this:
"This page isn’t working
localhost didn’t send any data.
ERR_EMPTY_RESPONSE"
Here is the relevant express endpoint:
app.post('/delete', function(req, res) {
var first = req.body.first;
var last = req.body.last;
db.collection("employees").remove({first:first, last:last}, function(error, response) {
if (error) throw error;
console.log("success");
});
});
If I do send data via res.send() or res.json(), then the entire front-end web page gets erased and replaced with whatever data was sent from the backend.
Often with form submission, you send the user to a different web page after submit. But in my case, I want the user to stay on the same page without reloading the page.
How do I get the error messages to go away in this case?

For the node/express part of the question, "How do I get the error messages to go away in this case?", you have to send some sort of response from the endpoint:
app.post('/delete', function(req, res) {
var first = req.body.first;
var last = req.body.last;
db.collection("employees").remove({first:first, last:last}, function(error, response) {
if (error) throw error;
console.log("success");
res.status(200).send({msg: `Deleted ${first} ${last}, RIP`}); //returning a status object, but you could return anything useful to the client code here.
});
});
This gets rid of the error, but you would still be redirected to a page showing the JSON output from the API.
Staying on the same page after submitting a form is discussed here and many other posts as well. You mention it is a React app--you might want to use that framework for making API calls from your frontend.

Related

How to send data from react.js to node?

I am a beginner in web devolopment and I'm developing an application using react and nodejs. I've been looking for ways to send the data from front end i.e, react(data received from the user) to nodejs code so that I can process it and send it back to the UI. I saw some resources mentioning that I can use fetch and axios but I can't quite follow it. So basically my application is about executing the pipe commands of linux. There will be few buttons to choose which command to execute(Like sort, uniq etc). There will be a text area to get the input text and a label to display the output. So how can I send the input data to the nodejs function so that I can process it with some built-in modules and return the output to the label.My code for text area looks like this
import { useState } from "react";
const Text_area = () =>{
const[text,setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
const data = {text};
}
return(
<>
<form onSubmit={handleSubmit}>
<label>Input here</label>
<textarea value= {text} required onChange={(e)=>setText(e.target.value)}/>
<button>OK</button>
</form>
</>
);
}
Share your thoughts please!
I assume you have only index route, that's why fetch is pointing to index.
const[text,setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
const newText= { text };
fetch("/", {
method: "POST",
headers: {"Content-Type": "application/JSON"},
body: JSON.stringify(newText)
})
}
Above, fetch method is used to send your data to relevant route in your node.js file.
And in your server.js file, you can code something like this to see if it works:
app.post("/", function(req, res){
res.send(req.body);
});
Please let me know if it works for you.
Think of your problem like a Form HTML element. How can a form send data to server?
Basically, they use HTTP GET/POST method. If you don't know it, Google! But for now, let just understand that: To send data from react.js to node, you need do something with HTTP GET/POST method.
<form action="/send_form" method="post">
<input type="text" id="fname" name="fname">
<input type="text" id="lname" name="lname">
<input type="submit" value="Submit">
</form>
form element has done it for you. This is why you see people mentioned axios because what if I don't use form? How can I do the same thing without form?
Then how do server receive information? You will do that by code something in Node.js. Googled yourself :>.
Then people mentioned Express.js. Think of it as "React" of Node.js, which mean it's a framework. You don't need to know "Express.js" to receive information sent from React.

NodeJS form submit issues

I am attempting to submit data in my NodeJS app. I've been using Postman with a single name entry in json and my app is able to detect the post body data. Screen shot below:
My problem is I can't get my html markup to submit data successfully. I provide the data to the form but the nodejs function receiving the submission shows that the request data is empty.
The following is the form markup:
<form id="join_queue" action="/join_queue" method="post" enctype="application/json">
<label for="">Please provide a name: </label>
<input type="text" name="name" id="name">
<input type="submit" value="Join">
</form>
And here is my Nodejs function responding to the form submission:
app.post('/join_queue', (req, res) => {
console.debug('Post body: ', req.body)
console.debug('Post param: ', req.params)
res.render('join.ejs')
})
All I get is Post body: {} and the same for params.
What am I doing wrong or missing here? How can I get my html form to behave the same as the postman form?
I needed to include the body-parser middleware in order to get form submission data as indicated here.
I.E:
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }));

Put method not updating MongoDB in Angular7 with NodeJS on the backend

I have this Angular7 app with NodeJS and MongoDB on the backend. I have tested out my put method with Postman and it works perfectly. The error lies in my Angular service component or possibly the component module that is using the service. No error messages are being displayed in the console. I have isolated it down to this--all the data is making it to the service, so the breakdown is between the service component and the Node api. Here's the method in my service.ts file:
updateSavings(pin: string, data){
const url = `api/accounts/${pin}`;
console.log(data);
return this._http.put(url, data, httpOptions)
.pipe(catchError(this.handleError)
);
}
Here is my Api.JS method that works fine with Postman:
router.put('/accounts/:pin', function(req, res, next) {
Accounts.findOneAndUpdate({pin: req.params.pin}, {savings:
req.body.savings}).then(function() {
//console.log(req.body.savings);
Accounts.findOne({pin:req.params.pin}).then(function(account){
//console.log(res.send(account))
})
})
})
Here is my component method that uses the services method:
depositSavings(data){
let y = this.accountsService.updateSavings(this.appComponent.rightPin,
data);
console.log(this.appComponent.rightPin);
return y;
}
}
Here is my template to show you what is going on there:
<input
type="text"
id="input"
[(ngModel)]="data"
[ngModelOptions]="{standalone: true}">
<br><br>
<button (click)="depositSavings(data)">Submit</button>
Any ideas what I have wrong? Thanks in advance guys.
You have to pass current _id as a first parameter and then whole object for update
router.put('/accounts/:pin', function(req, res, next) {
Accounts.findOneAndUpdate(req.params._id, {pin: req.params.pin, savings:
req.body.savings}).then(function() {
//console.log(req.body.savings);
Accounts.findOne({pin:req.params.pin}).then(function(account){
//console.log(res.send(account))
})
})
})
I handled the problem. As there were no error messages with this, it made it more challenging to figure this one out. What I was missing was this inside of my service method:
return this._http.put(url, {"savings": data}, httpOptions).subscribe(data =>
{console.log("PUT request successful ", data)})
In place of just data, you use {"savings": data}.

redirect post request from post request

trying to send post form request to another server.
I'm getting post request from my localhost lets say on POST /deposit
and I want later to redirect user to payment website with some kind of this data
​form to which I want user to redirect after he posts to: localhost:3000/deposit
<form action='http://testpayment.com/pay' class='redirect_form' method='post'>
<input type='hidden' name='key' value='${data.api_id}'>
<input type='hidden' name='signature' value='${data.api_secret_key}'>
<input type="hidden" name='user_id' value='${data.user_id}'>
<input type="hidden" name="payment_method" value="master_card">
<input type="hidden" name="customproduct" value='[{
"productId":"deposit-${currencyPayway.currency.code}",
"productName":"Test Product",
"productType":"fixedProduct",
"currency":"${currencyPayway.currency.code}",
"amount":${amount}}]'>
<button type='submit'>Pay</button>
</form>
Post route:​
app.post('/deposit', function(req, res) {
// some logic applies here
//redirect part ???
});
Any ideas how to do it?
Thanks.
UPDATE:
Use case of what I'm ting to do:
Lets say we have multiply payment providers. On deposit action in any way after applying some logic we need to redirect user to payment provider website for card/account details input after which user will be redirect to my website back again by payment provider. Now front writes custom logic for all deposit methods each time. But I tries to decouple front from that stuff and handle it completely on backend and unify deposit process.
In most cases as I know, paymant gateway works like this:
you will create a form and as an URL you put your Payment Provider URL https://secure.paymentprovider.com/deposit
you will create a form get the data from user, send on server side to Payment Provider, as a return you should get a SessionId, some kind of unique key and then you redirect user but with a GET method to Payment Provivder url ie. https://secure.paymentprovider.com/deposit/{token/sessionId}
Here is an example PayU - http://developers.payulatam.com/en/web_checkout/
Maybe you can attach link to Payment Provider api?
use stream.pipe
https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
app.post('/', (req, res,next) => {
var request = require('request');
var pipe = req.pipe(request.post('localhost:3000/deposit'));
var response = [];
pipe.on('data',function(chunk) {
response.push(chunk);
});
pipe.on('end',function() {
var res2 = Buffer.concat(response);
console.log(res2);
res.send(res2)
});
})

Cannot get session data from middleware in node.js

I have a function that gets the id of the user when she registers
user.save(function(err, id){
if(err) return next(err);
req.session.uid=id;
})
Then, I wrote this middleware
var User = require('../user');//contains the code above
module.exports = function(req,res,next){
var uid = req.session.uid;
if(!uid) return next();//if not logged in
else{//else is logged in
User.get(uid, function(err, user){
//get user object and pass it to locals
if (err) console.log("error from midd > "+err);
req.user = res.locals.user = user;
next();
})
}
}
I define my middleware in the app.js like so
var user = require('./lib/middleware/user');
app.use(session({resave:'false', saveUninitialized:'false', secret:'secret'}));
app.use(user); //<-- my middleware
app.use(express.static(path.join(__dirname, 'public')));
app.set('multimedia', __dirname + '/public/multimedia');
app.use(messages);
app.get('/register', register.form);
app.post('/register', register.submitit);
Then I check if there is an id in the locals and show the right menu, by using ejs
<%if (locals.user) {%>
<div id='menu'>
<a href='/post'>post</a>
<a href='/logout'>logout</a>
</div>
<%}else{ %>
<div id='menu'>
<a href='/login'>login</a>
<a href='/register'>sign up</a>
</div>
<%}%>
This never works. In every page, even if I am registered, I never see the menu for the registered users (post and logout).
I put many console.log all over the code and looks like the middleware never gets the session.uid.
console.log("req.session.uid = "+req.session.uid); inside the middleware always gives undefined, even though saving the user works and returns an id that I pass to session req.session.uid=id;
How do I fix this? Please advise because I am stuck.
Thanks
Note: I cannot be sure this is your error because you didn't paste the code around user.save(). But I'm enoughly confident that is the cause.
Session.Save(): This method is automatically called at the end of the HTTP response if the session data has been altered (though this behavior can be altered with various options in the middleware constructor). Because of this, typically this method does not need to be called.
As I can see here:
user.save(function(err, id){
if(err) return next(err);
req.session.uid=id;
})
You either:
Fail to save the new user and continue the process with next(err) (which end the HTTP response)
Or succeed and probably get stuck (<= not enough code shown to know what...)
In case of success you should probably call next() or next(null).
Because of that, the altered session (ie: req.session.uid=id;) is never saved. Thus, resulting in a failure of retrieving the uid in the middleware.

Resources