skip to Main Content

I have an Express server with a route for deleting a (psychology) experiment. (I have split my routes into multiple files. This route is in admin.js and thus its full route path is /admin/experiments/:expId)

router.route('/experiments/:expId')
    .delete(tokens.verifyToken, adminValidator.isAdmin, (req, res) => {
        const experimentId = req.params.expId;
        const db = req.db;
        db.removeExperiment(experimentId);
        renderExperiments(req, res, db);
    })

function renderExperiments(req, res, db) {
    let allExps = expStandard.getAllExperiments(db);

    res.render('adminExperiments', {
        allExps: allExps,
        approved_flag: APPROVED_EXPERIMENT,
        pending_flag: PENDING_EXPERIMENT
    });
}

This route deletes the experiment from the database and then calls a method which renders the associated adminExperiments.ejs view. This is an EJS template that simply creates an HTML table. Each row of the table corresponds to an experiment. And in each row I have included a delete button. Each delete button is associated with an EventListener for when the button is clicked:

A row from the table showing information about a given experiment

Here is the code in the associated js script (adminExperiments.js) which is executed on the client side:

document.addEventListener('DOMContentLoaded', registerDeleteExpListeners);


function registerDeleteExpListeners() {
    let deleteButtons = document.querySelectorAll('.btn_exp_delete');
    for (b of deleteButtons) {
        b.addEventListener("click", deleteExperiment);
    }
}

async function deleteExperiment(event) {
    // ???
}

Question:
What do I use in the event listener deleteExperiment() to connect to my Express route?

I tried using Fetch with a method header of "delete" and sending it to the URL for the route (/admin/experiments/:expId). Although I can send a delete request to the route and it is received, it does not render adminExperiments.ejs. Instead, a response object is sent back with a status of 200. That’s great but it’s not what I want. I want a new page rendered with the updated list of experiments.

2

Answers


  1. Chosen as BEST ANSWER

    Apparently, this cannot be done with Fetch. Fetch does exactly what it says: it fetches data. It does not redirect/render a new page.

    To do so, I included this line of code after using fetch to make the delete request:

    window.location.replace('/admin/experiments');

    In other words, I had to manually point the window to a different URL.


  2. it does not render adminExperiments.ejs. Instead, a response object is sent back with a status of 200.

    Well, yes, since a fetch request does not alter the location of the user, but sends a request in the background.

    @America Holloway’s answer is half correct. Be careful not to misunderstand fetch(), since it does not “fetch” data, but fetch a request. This request can retrieve data, update data, delete data, etc., it depends on the request, its method and what the server that receives the request does with it.

    And while window.location.replace(...); would indeed do the trick, do you really want the user to reload the page every time an experiment is deleted? You even say that with a delete fetch request the route is called, hopefully also deletes the item in the db, but only responds with a status of 200. This just means everything went ok, and you can then work from there.

    There are multiple ways to go from here. First, you would not need to send back the whole rendered page, but instead just something simple like res.json({success: true}) or anything else that lets you distinguish on the client-side if the request succeeded or not.

    From there, on the client-side, you need to react to the response of the request. There are far too many ways to go about this, but here are some examples of what I would do:

    • since you are using EJS, you could put the HTML of the table in a new file, e.g. experiments-table.ejs, put that in the page as

      <%- include('../path/to/experiments-table.ejs', {/*properties*/}) %>
      // this essentially works similar to the render() method
      

      Finally, change the route handler of /admin/experiments/:expId so that it just renders that partial again. On the client-side, you can then simply replace the table.

    • something different, but simple, would be to delete that row on success. So either work with HTTP status codes and delete the row on status 200, show error on status 4xx/5xx, etc., or do something like above res.json({success: true}) and delete the row if it’s true.

    As said before, there are many many other ways to do this, it depends on how you want to do it. You had it already right with the fetch request, all you need to implement is what happens after the response.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search