Jeff Matthews
Jeff Matthews

Reputation: 592

Javascript: Dynamic Function with Parameter

This is kind of tricky, but I need to make the large code block below generic.

I have a number of views that follow the same format: A table full of rows, where each row contains a delete icon. Each icon has a data-id attribute which is the item's _id in the database.

I am wiring the click action on each icon to where it opens a standard dialog to ask for confirmation. As you can guess, the "Yes" button of the dialog will have an onclick which calls the desired function with a parameter of the item's _id. e.g., setting onclick = deleteContact(fdke75jdsgtd7i)

Let's say I have 3 tables: Contacts, Cases and Firms.

I got all the wiring to work for any given table, provided I copy and paste the following code block in every view with the caveat that I have to use the commented onclick line instead of the generic, uncommented line below it.

let deleteItemAnchors = document.getElementsByClassName("delete-item");

Array.from(deleteItemAnchors).forEach( (item) => {

    item.addEventListener('click', () => {

        // Highlight the selected row.
        highlightedTableRow = item.closest("tr");
        highlightedTableRow.classList.add("table-warning");

        // The record's _id is in the data-id attribute.
        let itemId = item.getAttribute("data-id");

        let buttons = [{
            //onclick: () => { removeTableRowHighlight(); deleteContact(itemId); },
            onclick: () => { removeTableRowHighlight(); deleteFunction(itemId); },
            text: "Yes"
        }, {
            onclick: () => { removeTableRowHighlight(); },
            text: "No",
            class: "btn-secondary"
        }];

        let confirmDelete = new CustomDialog("Delete this " + recordType + "?", 'Click "Yes" to delete it.  Press "No" to cancel.', buttons);

    });

});

Here is an example of the function called when the button is clicked:

function deleteContact(itemId) {
    console.log("You deleted the item with id = " + itemId);
}

Bear in mind, it is only working if the commented onclick line is live, and the generic line right below it is comment out.

I want to stop recreating the big block of code for every view by moving it to a re-usable function which can be called from each of the 3 views as follows:

let deleteFunction = () => { deleteContact(); };  
wireDeleteIcons("Contact", deleteFunction);


let deleteFunction = () => { deleteCase(); };
wireDeleteIcons("Case", deleteFunction);

So, I moved the code block to a function called, "wireDeleteIcons," which accepts:

From my Contacts view, I am calling:

let deleteFunction = () => { deleteContact(); };  
wireDeleteIcons("Contact", deleteFunction);

It is all working so far, except for the deleteFunction(itemId) call when the icon is clicked.

If you look back up at the big code block, check out the line below the commented onclick line.

I am trying to add the parameter, itemId, to the function that was passed. On testing, it makes it all the way to my deleteContact() function, but it doesn't pass in the _id. So, my console.log shows, per my deleteContact() function, "You deleted the item with id = undefined"

How can I pass the function generically, and insert the parameter into it from within my generic wireDeleteIcons() function?

Upvotes: 0

Views: 53

Answers (1)

Barmar
Barmar

Reputation: 782785

Your deleteFunction() needs to take an argument:

let deleteFunction = (id) => deleteContact(id);

But you don't really need the deleteFunction variable. Just write:

wireDeleteIcons("Contact", deleteContact);
wireDeleteIcons("Case", deleteCase);

The definition of wireDeleteIcons should be something like this:

function wireDeleteIcons(tableId, deleteFunction) {
    let deleteItemAnchors = document.getElementById(tableId).getElementsByClassName("delete-item");

    Array.from(deleteItemAnchors).forEach( (item) => {

        item.addEventListener('click', () => {

            // Highlight the selected row.
            highlightedTableRow = item.closest("tr");
            highlightedTableRow.classList.add("table-warning");

            // The record's _id is in the data-id attribute.
            let itemId = this.getAttribute("data-id");

            let buttons = [{
                onclick: () => { removeTableRowHighlight(); deleteFunction(itemId); },
                text: "Yes"
            }, {
                onclick: () => { removeTableRowHighlight(); },
                text: "No",
                class: "btn-secondary"
            }];

            let confirmDelete = new CustomDialog("Delete this " + recordType + "?", 'Click "Yes" to delete it.  Press "No" to cancel.', buttons);

        });

    });
}

Upvotes: 1

Related Questions