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);
}
Your problem seems to be identifying the clicked row after a click has happened.
We can solve this in multiple ways:
target
property:
addEventListener()
.
onevent
property. Only one handler can be added this way.window.event
.onclick
on each row:
this
to the handler function (e.g. <tr onclick="RowHandler(this)">
). this
in inline events will refer to the clicked element.<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.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>
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>
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>
).