Search code examples
javascriptevent-handling

JavaScript click handler for row receives cell as target


I have a multi-column, multi-row table. Each row has a unique "data-index" attribute. I added a click event listener on each row. However, when I click on the row, the cell I happen to be over when I click becomes the target for the callback. In order to get the "data-index" attribute, I must use event.target.parentElement.getAttribute( "data-index" )

Consider this ...

<!DOCTYPE html>
<html>
  <body>
    <table>
      <tr data-index="0" onclick="handler(event)">
        <td>11</td><td>12</td><td>13</td>
      </tr>
      <tr data-index="1" onclick="handler(event)">
        <td>21</td><td>22</td><td>23</td>
      </tr>
      <tr data-index="2" onclick="handler(event)">
        <td>31</td><td>32</td><td>33</td>
      </tr>
    </table>

    <script>
      function handler ( event ) {
        console.log( event.target.innerText );
        console.log( event.target.getAttribute( "data-index" ) );
        console.log( event.target.parentElement.getAttribute( "data-index" ) );
      }
    </script>
  </body>
</html>

Just to be clear; I'm interested in the row, not its cells. It's the row that "owns" the data attribute, so ...

Why is the event target the cell and not the row? (None of the cells have event listeners.) At the very least, this is very unintuitive; am I doing something wrong?


Solution

  • Use event.currentTarget instead. target is the element triggered the event (you can't click the row since the cells are inside it and cover the row preventing from being clicked directly).

        <table>
          <tr data-index="0" onclick="handler(event)">
            <td>11</td><td>12</td><td>13</td>
          </tr>
          <tr data-index="1" onclick="handler(event)">
            <td>21</td><td>22</td><td>23</td>
          </tr>
          <tr data-index="2" onclick="handler(event)">
            <td>31</td><td>32</td><td>33</td>
          </tr>
        </table>
    
        <script>
          function handler ( event ) {
            console.log( event.currentTarget.innerText );
            console.log( event.currentTarget.getAttribute( "data-index" ) );
            console.log( event.currentTarget.parentElement.getAttribute( "data-index" ) );
          }
        </script>

    Another way is to use event.target.closest('tr') to find a td's tr:

        <table>
          <tr data-index="0" onclick="handler(event)">
            <td>11</td><td>12</td><td>13</td>
          </tr>
          <tr data-index="1" onclick="handler(event)">
            <td>21</td><td>22</td><td>23</td>
          </tr>
          <tr data-index="2" onclick="handler(event)">
            <td>31</td><td>32</td><td>33</td>
          </tr>
        </table>
    
        <script>
          function handler ( event ) {
            const $tr = event.target.closest('tr');
            console.log( $tr.innerText );
            console.log( $tr.getAttribute( "data-index" ) );
            console.log( $tr.parentElement.getAttribute( "data-index" ) );
          }
        </script>