0

I have this code (opt1) to get the text of the cell, which is clicked, but this alerts all of the objects in the table as its in a loop. But when I place it outside the loop I just get a random text from the table and not the one which is clicked (opt2).

I need the textContent of the cell, which is clicked, once, and not any other.

FYI: the cell contains multiple <td> inside <tr>.

The current method gets me the name text either of all cells (opt1) or the last cell (opt2)

HTML:

<table id="table">

        <tr class="cell" onclick="RowHandlers()">
            <td class="name">Name</td>
            <td class="date">Date</td>
            <td class="subject">Subject</td>

        </tr>

    </table>

opt1

function RowHandlers() {
    var table = document.getElementById("table");
    var name;
    for (var i=1;i<table.rows.length;i++) {

        name = table.rows[i].cells[0].innerText;

        alert(name);
    }
   
}

opt2

function RowHandlers() {
    var table = document.getElementById("table");
    var name;
    for (var i=1;i<table.rows.length;i++) {

        name = table.rows[i].cells[0].innerText;

       
    }
    alert(name);
}
  • There are basically two types data in your setup, text content which is the text in the `` or anything between the tags of an element ex.`
    `text`
    `, ``text`` and then there's `.value` ``. ATM your code is trying to get the former whilst you probably want the latter. If you want a definitive answer, please provide the HTML and state exactly what data you want, the former, the latter, or both?
    – zer00ne Jun 20 '22 at 09:59
  • You mentioned there were text elements as in ``s? – zer00ne Jun 20 '22 at 10:25
  • @nertz Why can you not use the first cell? What is different about it? Can you please provide _all_ the relevant HTML? – Oskar Grosser Jun 20 '22 at 11:15
  • @nertz it sounds like you are intentionally changing your criteria slightly each time I have adjusted my answer. There would be a point when someone that earnestly sought out an answer would've gotten there by now. – zer00ne Jun 20 '22 at 16:07

2 Answers2

2

Your problem seems to be identifying the clicked row after a click has happened.

We can solve this in multiple ways:

  1. In JS, use the event object's target property:
    1. (Preferred) Add handler via addEventListener().
      1. Use a single handler by making use of event propagation.
      2. Add handlers to each row.
    2. (Discouraged) Add handler via onevent property. Only one handler can be added this way.
    3. (Deprecated) Use the global object window.event.
  2. (Discouraged) In HTML, use inline event onclick on each row:
    1. Pass this to the handler function (e.g. <tr onclick="RowHandler(this)">). this in inline events will refer to the clicked element.
    2. Add IDs to each row (e.g. <tr id="row1">). For each row, pass its ID to the function (e.g. onclick="RowHandler('row1')"). Search for the element by the passed ID.

Using addEventListener()

To add a listener, pass the event type and the listener:

const input = document.querySelector("input");
const button = document.querySelector("button");

button.addEventListener("click", clickHandler);

function clickHandler(event) {
  console.log(input.value);
  input.value = "";
}
<input><button>Click me!</button>

Event propagation

Because events bubble up the DOM, <table>'s listener will also fire when its rows are clicked. We can use event.target to get the event's origin element and find the clicked row:

const table = document.querySelector("table");
table.addEventListener("click", tableClickHandler);

function tableClickHandler(event) {
  const row = event.target.closest("tr.cell"); // event.target may be a <td>
  
  const isInRow = Boolean(row);
  const isFirstRow = row === table.rows[0];
  if (!isInRow || isFirstRow) return;
  
  const name = row.cells[0].textContent;
  const date = row.cells[1].textContent;
  const subject = row.cells[2].textContent;
  
  console.log("Clicked:", { name, date, subject });
}
table,td{border:1px solid}
<table>
  <tr>
    <th>Name</th>
    <th>Date</th>
    <th>Subject</th>
  </tr>
  <tr class="cell">
    <td class="name">Some name</td>
    <td class="date">01-01-1999</td>
    <td class="subject">Some subject</td>
  </tr>
  <tr class="cell">
    <td class="name">Another name</td>
    <td class="date">02-02-2020</td>
    <td class="subject">Another subject</td>
  </tr>
</table>

Regarding your solutions

You are missing some way of identifying the clicked element; see my suggestions above.

In opt2, you are looping through all rows, but constantly overriding the variable name before using it. Therefore it is the same as only reading the name of the last row.

You may want to use .textContent over .innerText, because it doesn't cause a reflow. If visibility of the content matters, choose .innerText, otherwise .textContent.

A table usually consists of sections (e.g. <thead>, <tbody>, <tfoot>, or an implicit section). Each section consists of rows; each row consists of cells. Therefore, your class name "cell" for a row may be confused with actual table cells (<td>/<th>).

Oskar Grosser
  • 2,804
  • 1
  • 7
  • 18
0

Please check this.

const [row] = document.getElementsByClassName('cell');
row.addEventListener('click', function(event) {
  console.log(event.target.innerText);
})
<table id="table">

        <tr class="cell">
            <td class="name">Name</td>
            <td class="date">Date</td>
            <td class="subject">Subject</td>

        </tr>

    </table>
Mina
  • 14,386
  • 3
  • 13
  • 26