Does Express require me to DELETE using a POST route? - javascript

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.

Related

Include two https requests in Node js via the same html button

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
}

Laravel resource route delete from axios

I would like to setup axios to delete a record using a resource route:
axios.delete('/job-management', this.deletedata).then((res)=>{
console.log(res);
})
For my routes I have:
Route::resource('job-management', "PositionsController", [ 'as' => 'jobs']);
Now, in my PositionsController I have:
public function destroy(Positions $positions) {
return $positions;
}
But the above always returns "method not allowed". How can I handle a delete request with the axios delete() method?
Laravel throws the MethodNotAllowedHttpException when we attempt to send a request to a route using an HTTP verb that the route doesn't support. In the case of this question, we see this error because the JavaScript code sends a DELETE request to a URL with the path of /job‑management, which is handled by a route that only supports GET and POST requests. We need to change the URL to the conventional format Laravel expects for resourceful controllers.
The error is confusing because it hides the fact that we're sending the request to the wrong URL. To understand why, let's take a look at the routes created by Route::resource() (from the documentation):
Verb URI Action Route Name
GET /job-management index job-management.index
GET /job-management/create create job-management.create
POST /job-management store job-management.store
GET /job-management/{position} show job-management.show
GET /job-management/{position}/edit edit job-management.edit
PUT/PATCH /job-management/{position} update job-management.update
DELETE /job-management/{position} destroy job-management.destroy
As shown above, URLs with a path component of /job-management are passed to the controller's index() and store() methods which don't handle DELETE requests. This is why we see the exception.
To perform a DELETE request as shown in the question, we need to send the request to a URL with a path like /job-management/{position}, where {position} is the ID of the position model we want to delete. The JavaScript code might look something like:
axios.delete('/job-management/5', this.deletedata).then((res) => { ... })
I've hardcoded the position ID into the URL to clearly illustrate the concept. However, we likely want to use a variable for the this ID:
let positionId = // get the position ID somehow
axios.delete(`/job-management/${positionId}`, this.deletedata).then((res) => { ... })
The URL in this form enables Laravel to route the DELETE request to the controller's destroy() method. The example above uses ES6 template string literals because the code in the question suggests that we're using a version of JavaScript that supports this feature. Note the placement of backticks (`) around the template string instead of standard quotation marks.
as I can see in your code above, you pass Positionseloquent as a parameter to destroy method but in your vueJS you don't pass this object. for that you would pass it like this :
axios.delete('/job-management/${id}').then((res)=>{
console.log(res);
})
and the id param inside the url of ur axios delete, it can object of data or any think.
i hope this help you

Simple MEAN Stack issue

I have a express route;
router.get('/uni/:queryst', function (req, res) {
var choice = req.params.queryst);}
Where basically I use the queryst value from the URL to use it to query something in my database. On the front end, I need to have an input field where the user types the choice and hits submit and then it translates to something like /uni/valuehere on the browser and sending GET to express where it gets caught by the router I wrote above. I don't know how can I make the input field of HTML turn into a URL of the format /uni/valuehere .
As for testing the code initially I was directly typing the URL manually with the value I intended to verify to check if the data passed. Well, users are not going to type URL's directly to search, they will need a form and that is what I can't get my head around to how to turn the input field into a URL in a format /uni/WhateverTheUserHasTypedInTheFieldShouldAppearHere
Thanks in advance for the help. I am self learning the MEAN stack and have come a long way. I need support of experienced developers as I am currently stuck here.
While sending the request write (in controller):
$http.get('/uni/'+queryst).success(function(response){
// Write code using response
});
While on the server side write:
$http.get('/uni/:queryst',function(req,res){
var choice= req.params.queryst
// Code ....
});

use POST to retrieve specified item from DB

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.

Same URL - render different pages (EXPRESS)

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');
}
}

Categories