imagine this scenario, I want to update a book's detail. so I should have that book id, I do like this
router.get('/edit/:book_id', function(req, res) {
Products.getBookById(req.params.book_id, function(err,product){
//render
});
});
update this book
I'm done, my flow is correct but my only concern is the the url is not nice, like localhost:8000/books/update/3434050348984585646
How can I hide the url? how to use POST in my case?
Remove the :bookId from your route definition, and change your link to a form:
JS
router.get('/edit', function(req, res) {
Products.getBookById(req.params.book_id, function(err,product){
//render
});
});
HTML
<form action="edit" method="post">
<input type="hidden" name="book_id" value="3434050348984585646">
<input type="submit" value="Update this book">
</form>
Another option would be to use the well known POST/Redirect/GET pattern (which has the advantage of preventing double POSTs).
The advantage is that you do not have to use URL parameters (which may well have security impacts) or have to deal with hidden form fields.
So you receive a POST as usual, and after processing the parameters, you send a redirect message to the client, either with a code of 302 "Found" or (preferred) with a 303 "See Other" and the URL you want to redirect to. While sending a 302 may cause a client to use GET instead of the original request method to call the URL you redirected to (it usually does), the 303 code explicitly instructs the client to use GET, no matter what the original request method was.
Related
I have an HTML button that sends a POST request and would like to do some kind of verification before making the request here.
The verification involves a GET request, where I make sure that a certain table contains a certain value or not. After that, if the condition is valid I make the POST request else I use the value I fetched from the GET request.
Even though this sounds basic I'm not sure how to do this in Nodejs.
Here is how code is organized now,
Her is the HTML button:
<form action="/generate_survey" method="POST" id="gen_survey">
<button type="submit" class="btn btn-primary my-3">Get Survey Link</button>
</form>
And I have a router.js that includes all the routes:
route.get('/generate_survey', controller.test)
then here in the controller.js, I have the db and other call functions.
So here is the test function where I want to make the request
exports.test = (req, res)=>{
.....
}
Should I put the GET request results in a variable and then depending on that I make the POST request?
If so I'd like to see an example of how to something similar in Nodejs
Thanks
In Angular we can do this way. so hope same applies to Nodejs as well. adding form method just for ref. you can check the actual one.
form onsubmit="do_something()"
do_something(): boolean{
// do get operation here
return true; // submit the form
return false; // don't submit the form
}
I'm working with basic HTML/CSS frontend, I currently have a landing page with a form on it that sends some data to a database. When the request is done, it is expecting some sort of response. In this case, I am re-rendering the page, however, I want to replace the form with some sort of a thank you message, something so the user knows that it has sent correctly. I have tried the solution of simply having a separate near identical page with the form removed and replaced, however, this kind of code cloning seems like an inefficient way to do it. Is there a way I could do some sort of front-end DOM manipulation from within my node app instead?
Generally, if you want to manipulate how the DOM looks server side you would need to render your entire page server side and then send it to the front end.
If you want to simply manipulate the DOM after a request is received on the front end, whic is a pretty regular practice for this type of stuff; regardless of the back end language(s) used, you can:
Submit form
Let user know form is submitting to server (Best practice for UX)
Once you receive your response, manipulate the DOM however you would like
For this use case, I've taken advantage of the async/await syntactical pattern which will allow you to wait for a response while not ending up in a nested callback pattern.
The attached snipped will fake a request to the server through a set timeout value, and echo what you put into the form back to the page. It's on a three second delay and uses AJAX to make the request.
*You can simplify this code by removing some logging and comments, but I've made it more verbose than necessary for learning purposes.
**I've purposely put the submit button outside of the form element so that it does not auto-post on submit. If you want to submit this way, you can use event.preventDefault() within the function, catch the event before it bubbles, and do this instead. Either way will work fine.
async function getDataAsync0(data) {
return new Promise(async (res) => {
setTimeout(()=>{
res(data);
},3000)
});
}
$(`#submitButton`).click(async () => {
// Create div to display what's going on
let statusAreaElement = $(`#statusArea`);
// Submit Event
statusAreaElement.html(`Submitted... Waiting for response...`);
// Cache input element
let inputElement = $(`#input01`);
// Cache form element
let formWrapperElement = $(`#formWrapper`);
// Cache success message div
let successMessageElement = $(`#successMessage`);
// Get value
let value = inputElement.val();
// Send value, await response;
let response = await getDataAsync0(value);
statusAreaElement.html(`Response returned -> ${response}`)
// Clear input element
inputElement.val(``);
// Hide form, show success message
formWrapperElement.hide();
successMessageElement.show();
})
#statusArea {
position: absolute;
left: 0;
bottom: 0;
}
#successMessage {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="formWrapper">
<form>
<label for="input01">Form Input</label>
<input id="input01" type="text">
</form>
<button id="submitButton">
Submit Form
</button>
</div>
<div id="successMessage">
Thanks for your submission!
</div>
<div id="statusArea">
</div>
JSFiddle offers an echo service so I've also written the same code into a fiddle so you can see it actually call the server and echo back the response.
Here is that link:
https://jsfiddle.net/stickmanray/ug3mvjq0/37/
This code pattern should be all you need for what you are trying to do. Again, this request is also over AJAX so the DOM does not need to completely reload; if you are actually going to be making a regular post (without AJAX) to the server and then reload the page afterwards, you can do the same thing - or simply construct the new page you wanted to send to them server side and then redirect them from there.
I hope this helps!
Can I do DOM manipulation within an Express POST request?
No. The server builds up a response (a big chunk of html), that gets sent to the client which parses it and builds up the DOM. You cannot directly work with that from the server.
However you can:
1) Modify the html the server sends (have a look at express.render)
2) Run a clientide script that opens a connection to the server (websockets, AJAX) and then mutate the DOM there when the server sends something.
The following code successfully deletes a record when a button is clicked and confirmed:
Router (Express):
router.post('/meetings/delete/:slug', catchErrors(meetingController.deleteMeeting));
Controller:
exports.deleteMeeting = async (req, res) => {
const slug = req.params.slug;
const meeting = await Meeting.remove({ slug });
req.flash('success', 'meeting successfully deleted!');
res.redirect(`/meetings`);
};
View Template (Pug/Jade):
form.delete-meeting-form(method='POST' action=`/meetings/delete/${meeting.slug}?_method=DELETE`)
input.button.button--delete(type='submit' value='DELETE MEETING' onclick='return confirm("Are you sure you want to delete this meeting? (Cannot be undone)")')
This code works great as-is. However, it seems strange to me that I seem to be required to use a POST route in order to complete my DELETE request. When I attempted to use router.delete to form the route, it did not work.
I understand that HTML doesn't support DELETE and PUT/PATCH requests very well, but why was it a problem to name my Express route delete? Did I do something wrong?
Delete will work fine with express. Regular HTML forms do not support delete. If you add a delete route to your application you can test the delete method with ajax (fetch, axios, jQuery, etc.) or curl:
curl -X "DELETE" http://foo/meetings/some-meeting
If you'd like to be able to use regular HTML forms with delete, check out the method-override middleware. The custom logic section shows how you'd create an override that's similar to how Rails handles method overrides.
This is a matter of convention. jQuery (and Javascript in general) supports DEL and PUT in addition to GET and POST, but nothing is stopping you from deleting using GET or POST, as you are doing it above. It is a good practice to synchronize your api calls with corresponding calls but it takes a bit more effort to setup.
Is it possible to render different pages for the same URL in express?
For example, if I click on #login1, I want to be sent to /login_page/. If I click on #login2, I should still be sent to /login_page/. Each time, I want to render different htmls depending on which #login I clicked.
So I want it to look like this.
Client:
$("#login1").click(function(){
window.open(/login_page/,'_parent');
});
$("#login2").click(function(){
window.open(/login_page/,'_parent');
});
Server:
app.get('/login_page/', users.login_page1); //if I clicked #login1
app.get('/login_page/', users.login_page2); //if I clicked #login2
Thanks a lot for any help.
Basically you need some field in the request to convey this information.
The simple thing: the URL, as the web was designed
If you're too cool to have the URLs be different, you can use the query string
window.open('/login_page?from=login2', '_parent');
If you're too cool for the query string, you could set a cookie
If you're too cool for a cookie, you could request the page via ajax with xhr.setRequestHeader
If you're tool cool for a custom ajax request header, you could add an image with a tracking pixel src attribute to the DOM just prior to loading the login_page and detect that in the server side session and render a different page accordingly
So in summary there are at least a half-dozen ways to technically achieve this. Only the URL and the query string are reasonable, IMHO.
if I got it correctly you just want to invoke different controllers upon the same request with no parameters?
you know you can just parametrise the url and get the result you need with small control logic on the server side.
I don't believe it's possible to do this without any parameters. One solution could look like this
client:
$("#login1").click(function(){
window.open(/login_page/1,'_parent');
});
$("#login2").click(function(){
window.open(/login_page/2,'_parent');
});
Server:
app.get('/login_page/:id', function(req, res){ //if I clicked #login1
if(req.params.id == 1){
res.render('index1.html');
} else {
res.render('index2.html');
}
}
There's a button, when it is clicked(html onclick) it redirects to another page. In javascript there's a function, that writes some new values into a database table when this button is clicked. My problem is: redirecting takes place before the data is written into the database, so on the new page i still have the old values. Is there an easy way to invert these steps(redirecting, writing into database)? Thanks for your advise
just move the redirection into the callback of an ajax call, say you have
Save data
<script type="text/javascript">
$(document).ready(function() {
$("#savedata").click(function() {
$.post('/savemydata/', { mydata: 'data' }, function(data) {
window.location.href = '/newpage/'
});
return false;
});
});
</script>
if the button actually submits the form, then you might probably want to hide the button instead and then just trigger it after your post simply by adding:
$("#buttonID").trigger('click');
Use ajax to write the data, then in the callback of the ajax throw in the redirect. This will ensure that the redirect does not happen until the information is written to the database. It would help to see some of your code to make a better answer. Also, this would most likely be best done with jQuery if you are new to ajax.
Move the code that redirects to a new page into the callback for your ajax save request.
Something like this:
$.post('/savemydata/', { my: 'data' }, function(data) {
//the Ajax post has been completed successfully, so now we redirect
window.location.href = '/newpage/'
});
That depends on how you are writing to the database. But the usual and recommended way to transport data to your server when loading a new page is the use of URL parameters. If you use something like
<form action="/next.php" method="POST">
<input type="hidden" name="data" value="values" />
<button type="submit" value="Next Page" />
</form>
or
Next Page
// also simply usable with
window.location = "/next.php?data=values";
you can be sure that
the data reaches the server,
can be processed (written to the database) before
the requested page is returned.
You could also make use of cookies. Just write your data values into document.cookie, and they will be transported to the server with the same request that asks for the new page.