Home > Software engineering >  When using node, mongoose, and express why do my delete functionality work with a GET method but not
When using node, mongoose, and express why do my delete functionality work with a GET method but not

Time:07-29

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>
  • Related