Given the following expressjs server code which conditionally responses to the same entry point, I want to display error message or open download dialog based on server's response. It possible and if so, what i s a recommended way to do it?
app.get('/download', (req, res) => {
if (conditionA) {
return res.status(403).send({err: 'Message I want to display with frontend JS'});
} else {
return res.sendFile('file I want to send');
}
});
Related
I am building a web app, including routes for authentication.
The Problem: When a registration succeeds I want to redirect to /login, but also include render options. But when I render the login.ejs the url stays /register.
The Options: I either have to find a way to use res.render and change the url OR use res.redirect and also pass render variables.
This is minimal code to show my problem:
app.get("/login", (res, req) => {
res.render("login.ejs", {flag: ""})
}
app.post("/register", (res, req) => {
// registration logic
if(success) {
res.render("login.ejs", {flag: "registration_success"})
}
}
the url shown is what you write in app.post("/someURL" not what you redirect to.
so if u want to redirect to login page after successful registration, simply redirect to "/login". it renders "login.ejs"
about the part that you probably want to show a sign up success message, u can use 'flash' package; it helps you add data to memory and get it in client side and show a success message. I use sweetalert2 in such a way:
in back-end code:
req.flash('a-name-you-want', { flags, you, want });
to get these info in front-end:
<% let yourData = req.flash('the-name')
if(yourData.length) {
// do sth to the data
}%>
I hope it helped you!
My problem is similar enough to this but also different and the answers aren't working for me.
I have a form to post and I need to display a message on the page whether it entered the data to the database successfully or not. So I have:
app.post('/add_new', upload.single('image'), function add_new(req, res, err)
{
var image = req.body.image;
// do some checks and try to insert
if (err){
res.render('page_name',{images:images, message:'There was an error'})
}
else{
images.push(image);
res.render('page_name',{images:images, message: 'Success'})}
}
}
The error/success messages are handled on the client side.
My problem is that it doesn't actually complete the post. It renders the page with the error/success message correctly but the URL looks like 'my_site.com/add_new', and if the user refreshes the page for any reason, it sends that 'form resubmission' alert, which causes problems. I need it to go back to 'my_site.com' and display the message.
I have found that doing
res.redirect('back')
returns to the correct page but obviously doesn't display the message.
I have noticed a few answers recommending
res.end('Success')
but that just displays a white page with the word 'Success' - I don't know how anyone thinks that's an acceptable solution!
EDIT:
Following Vinay's answer, my code now reads like:
app.post('/add_new', upload.single('image'), function add_new(req, res, err)
{
var image = req.body.image;
// do some checks and try to insert
if (err){
req.session.msg='error adding';
res.redirect('page_name');
}
else{
images.push(image);
req.session.msg='success';
res.redirect('page_name');
}
}
and this to get the page:
app.get('/page_name', is_logged_in, function(req, res) {
if(req.session.msg){
res.render('page_name', {images: images, user:req.user, message: req.session.msg});
setTimeout(req.session.msg="", 4000);
}
else{
res.render('page_name', {images: images, user:req.user, message:''});
}
});
But I am still finding that the error message persists when the page is refreshed. Have I made a mistake?
currently you are doing this
if (err){
res.render('page_name',{images:images, message:'There was an error'})
}
else{
images.push(image);
res.render('page_name',{images:images, message: 'Success'})}
}
you are getting url like this to 'my_site.com/add_new', which is correct rendering means your are loading/rendering html page to particular route which is '/add_new'.
There may be a two solution
1st solution
res.redirect('/?msg=' + string);
and on home page
app.get('/', function(req, res){
if(req.query.msg){
// display error message
}else{
// else do not display error
}
});
2nd solution
req.session.msg = "message here";
res.redirect('/');
and on home page you can do like this.
if(req.session.msg){
//display error message here
// after displaying msg in that last this
setTimeout(req.session.msg="", 3000); // this will clear a session after 3 seconds, so next time it will not display the msg.
} else {
//or display home page without error.
};
you can use one of them.
Im simply trying to download a file from the server and prompt the download in the browser for the user to see.
What i have right now:
Client
export function downloadTemplateAction(questionnaire) {
return dispatch => {
dispatch(downloadTemplateRequestAction(questionnaire));
return request
.get(downloadGETUrl)
.end((err, res) => {
if (err) {
console.log("Download ERROR", err)
dispatch(downloadTemplateFailureAction(err, questionnaire));
} else {
console.log("Download Success", res.body)
dispatch(downloadTemplateSuccessAction(res.body, questionnaire));
}
});
}
}
Server:
export function downloadTemplateDocument(req, res){
res.download('template/Example.docx');
res.end();
}
Im facing two problems:
First: When trying to download the file via the function of the Client, the response body is null but success and nothing more happens.
Second: When contacting the get API via the browser localhost:3002/api/download, the download works but the received file is empty. There should be text in it.
What am i doing wrong here?
Browser can't prompt a download progress because your request is sent via XMLHttpRequest.
Physical access to the file is needed for the browser to be aware of any download.
You could use download attribute to tell browser to download linked ressource.
original answer
I am not sure how to use an ajax POST to POST from a Jade Page to Node JS. If someone can provide an example or tell me what I am missing from the script I have, please let me know.
This is the script file:
//Add friends
$('.addContact').click(function() {
$.post('/addContact',
{friendRequest: $(this).data('user')});
if($(this).html!=='Contact Requested') {
return $(this).html('Contact Requested');
}
});
The url I have for a POST on my app.js file is:
app.post('/addContact', user.addContactPost);
I am trying to post true for a click event on the button Add Contact and change it to Contact Requested if the data in the db is shown as true.
This is the jade file:
extends layout
block content
div
legend Search Results
div#userResults
for user in ufirstName
a(href='/user/#{user.id}')
p #{user.firstName} #{user.lastName}
button.addContact Add Contact
The route file is this:
exports.addContactPost = function(req, res, err) {
User.findByIdAndUpdate(req.signedCookies.userid, {
$push: {friendRequest: req.body.friendRequest}
}, function(err) {
if(err) {
console.log("post2");
return console.log('error');
//return res.render('addContactError', {title: 'Weblio'});
}
else {
console.log('postsuccess');
//alert('Contact added');
res.json({response: true});
}
});
};
If you are posting AJAX request, then you are expecting from JS on client-side to get some response, and react to this response accordingly.
If it would be separate request to another page - then probably rendering whole page - would be actual option.
But as you just need to get response from server and then update your front-end without reloading based on response, then you need to response from server on this POST request with some JSON. And then on client-side, do some templating, use jQuery or some templating libraries on client side for it.
Everything looks good I just think the $.post code is a little off. This might fix your problem.
$('.addContact').click(function() {
$.post('/addContact', { addContact : true }, function(data){
console.log('posting...');
$('.addContact').html(data);
});
...
});
The object I added to the $.post is what is going to be sent to the server. The function you specified at the end is your callback. It's going to be called when the function returns. I think that may have been some of your confusion.
Your node route should look something like this
exports.addContactPost = function(req, res, err) {
User.findByIdAndUpdate(req.signedCookies.userid,{
addContact: req.body.addContact
}, function(err) {
if(err) {
console.log("post2");
res.render('addContactError', {title: 'Weblio'});
}
//assuming express return a json object to update your button
res.json({ response : true });
});
};
In my Node.js application, I have a function (routed by Express) which presents a form to the user:
app.get('/register', function (req, res) {
res.render('form');
});
I have another function, routed to the same URL, but which handles POST requests, which receives the data submitted by the previous form. If the form does not validate, it redirects the user back to the form; otherwise, it does what should be done:
app.post('/register', function (req, res) {
if (validate(req.registerForm)) return res.redirect('back');
persistStuff(req.registerForm, function (err, data) {
// Do error verification etc.
res.redirect('back')
});
});
What I want to do is to send a error message to be presented, in the line:
if (validate(req.registerForm)) return res.redirect('back');
To write something like
if (validate(req.registerForm)) return res.render('form', {msg:'invalid'});
is unacceptable because I want to follow the POST-REDIRECT-GET pattern. I could do something like
if (validate(req.registerForm)) return res.redirect('/register?msg=invalid');
but it would hardcode an URL in my code and I'd prefer to avoid it. Is there another way to do it?
You need to use flash notifications, and it is built into express.
You'll add a message like so: req.flash("error", "Invalid form...");
You'll need a dynamic handler to add the messages to your rendered template, or you can check out the ones TJ has made for express. (express-messages)
You could simply have it redirect as res.redirect('..?error=1')
the ? tag tells the browser that it is a set of optional parameters and the .. is just a pathname relative recall (like calling cd .. on terminal to move back one directory)
and you're browser will direct to the appropriate page with that tag at the end: http://.....?error=1
then you can simply pull the error on the appropriate page by doing a:
if (req.param("error" == 1)) {
// do stuff bassed off that error match
};
you can hardcode in several different error values and have it respond appropriately depending on what error occurred