I am working on a crud project and I want to delete a item by id using MongoDB, express, and node.
here is the functionality for me to delete an item:
router.get('/delete/:id', async (req, res) => {
try {
const topic = await Topic.findById(req.params.id)
await Topic.remove({ _id: req.params.id })
res.redirect('/dashboard')
} catch (error) {
console.log(error)
}
})
here is the ejs portion for when a user click on the item to be deleted:
<div >
<a href="/edit/<% topic._id %>"><i ></i></a>
<a href="/delete/<%= topic._id %>"><i ></i></a>
</div>
this code actually works but when I change the get method to a delete method like this:
router.delete('/delete/:id', async (req, res) => {
try {
const topic = await Topic.findById(req.params.id)
await Topic.remove({ _id: req.params.id })
res.redirect('/dashboard')
} catch (error) {
console.log(error)
}
})
it do not work. I get a message in the browser saying "Cannot GET /delete/62def4aae6c2c1914cfa145fer3" why is this? I should be using the delete method instead of get right? How can I make this work with the delete approach?
CodePudding user response:
Clicking on an <a>
tag performs a GET request. In order to hit your router.delete()
route, you have two options...
Option #1
Intercept the event with JavaScript and send an async DELETE
request.
Include a <script>
section in your view with something like the following...
// Delegated event listener
document.addEventListener("click", async (e) => {
const del = e.target.closest("a i.fa-trash");
if (del) { // clicked on a "trash" icon
e.preventDefault();
const { href } = del.closest("a"); // get the href
const res = await fetch(href, {
method: "DELETE", // send a DELETE request
redirect: "manual", // don't follow redirects
});
if (res.ok) {
// request successful
window.location = res.headers.get("location") ?? "/dashboard";
} else {
console.error(res);
}
}
});
In this scenario, you may not want to respond with a redirect since you're handling the follow-up action client-side. See this answer for more details
Option #2
Use the method-override middleware to simulate a DELETE
request.
Register the middleware in your app
const methodOverride = require("method-override");
app.use(methodOverride("_method", {
methods: ["GET", "POST"], // GET is not recommended, see below
});
and add the appropriate query string parameter to your links
<a href="/delete/<%= topic._id %>?_method=DELETE">
<i ></i>
</a>
Keep in mind that deleting via GET request can be very dangerous. I would at the very least recommend using a <form>
instead
<form action="/delete/<%= topic._id %>?_method=DELETE" method="POST">
<button type="submit" >
<i ></i>
</button>
</form>