Search code examples
javascripthtml-tablecell

Javascript get table cell content on click


    <table id="position">
        <tr><td>TL</td><td>TC</td><td>TR</td></tr>
        <tr><td>CL</td><td>CC</td><td>CR</td></tr>
        <tr><td>BL</td><td>BC</td><td>BR</td></tr>
    </table>
    <script>
    document.querySelector("#position td").addEventListener("click", function(){
    console.log(this.innerHTML);
});

Trying to get innerHTML of table cell <td> on click. It returns nothing. When I change selector to #position tr it returns data, but ONLY for first <tr> row, when I click on it. When clicking on second, third - returns nothing. Obviously, when I change selector to table #position it works fine and returns whole table.

I even tried to add class for every cell like <td class="cell">- document.querySelector(".cell").innerHTML returns content, but once again - ONLY for first <td> cell!

How to get clicked td and why is it behaving so strange? Also, is it possible to get clicked row/column number?


Solution

  • Add a single listener to the tbody of the table, and retrieve the clicked cell from the event object, like this:

    const tbody = document.querySelector('#position tbody');
    tbody.addEventListener('click', function (e) {
      const cell = e.target.closest('td');
      if (!cell) {return;} // Quit, not clicked on a cell
      const row = cell.parentElement;
      console.log(cell.innerHTML, row.rowIndex, cell.cellIndex);
    });
    <table id="position">
      <tr>
        <td>TL</td>
        <td>TC</td>
        <td>TR</td>
      </tr>
      <tr>
        <td>CL</td>
        <td>CC</td>
        <td>CR</td>
      </tr>
      <tr>
        <td>BL</td>
        <td>BC</td>
        <td>BR</td>
      </tr>
    </table>

    This technique is called event delegation, it takes the advantage of the event bubbling mechanism, where the events are fired on every ancestor element of the actual clicked element too. It's very useful, specifically when working with dynamic tables, and is handy to use with static tables as well.

    As you can see (in the console.log), table rows and cells have a specific row/cellIndex property. It's dynamic, and you can use those properties to get the "row/column number".