javascripthtmljquerydatatables

jQuery Events are not binding on buttons in a responsive datatable


I have a table

column 1 column 2 colum 3 [buttons]
data data data [Button][Button][Button][Button]

I then convert the HTML Table to a responsive datatable, with the buttons bound using a jQuery selector using the .on('click',fuction () {} ); construct. Now in tables that have not been collapsed due to the length of the table row the events are bound, but where datatables have been wrapped the events are not being bound.

It does not matter if I bind the events before or after the creation of the datatable, yet if I specifically bind to a button it works.

This is how I am binding the buttons, all the other buttons that match the selector are bond:


$('button[data-eh-location]').on('click', function () { alert('Wibble'); }; 

This is the thing I have noticed with the datatabe in that you have to bind things and create tooltips BEFORE your convert the HTLML table to a data table. But in this case it does not seem to be working

How a button is defined in the HTML:

<button type="button" data-eh-location="/@item.UniqueRefenceForLinks/Edit" class="btn btn-edit" title="Edit job application" data-bs-toggle="tooltip"><i class="fa-solid fa-pen-line fa-fw"></i></button>

If the table does not wrap the button is bound correctly


Solution

  • Handling events for dynamically created elements can be achieved by using event delegation.

    Using jQuery, you can use something like:

    $("table.s-table").on("click", "button[data-eh-location]", [handlerFunction]);
    //                              ∟ the designated element(s)
    

    But actually you don't need jQuery for it.

    This snippet may give you an idea how it works in plain js:

    // add the listener before anything is done
    document.addEventListener(`click`, handle);
    
    // a demo handler showing the text of the element clicked
    function handle(evt) {
      if (evt.target.dataset.clicktext) {
        console.clear();
        return console.log(`${evt.target.textContent} clicked`);
      }
      
      return true;
    }
    
    createTableHeader();
    
    // click the first header
    document.querySelector(`[data-clicktext]`).click();
    
    // add a header with a button (and click it) after 2 seconds
    setTimeout(() => {
        document.querySelector(`thead tr`)
           .insertAdjacentHTML(`beforeend`, 
             `<th><button data-clicktext="1">button!</button></th>`);
        document.querySelector(`thead th:last-child button`).click();   
      },
      2000
    );
    
    // create a table header
    function createTableHeader() {
      const table = document.createElement(`table`);
      table.insertAdjacentHTML(`beforeend`, `<caption>Example</caption>`);
      const head = table.insertAdjacentElement(
        `beforeend`, document.createElement(`thead`));
      const headerRow = head.insertAdjacentElement(
        `beforeend`, document.createElement(`tr`));
      
      [...Array(3)].forEach((_, i) => 
        headerRow.insertAdjacentHTML(
          `beforeend`, 
          `<th data-clicktext="1">header ${i+1}</th>`)
      );
      document.body.append(table);
    }
    table {
      th {
        cursor: pointer;
        font-weight: normal;
        padding: 1px 4px;
        &:hover {
          text-decoration: underline;
        }
        &:not(:first-child) {
          border-left: 1px solid #999;
        }
      }
      caption {
        padding: 2px;
        border-bottom: solid 1px #999;
      }
    }