3

I have a table in HTML, which is created as follows:

<table id="tableID" onclick="getRowData()" class="table table-hover"></table>

At first it gets populated with some initial data, which could make it look something like this:

From  Action  To
 a      1     b
 a      0     a

I want to be able to retrieve the data from an arbitrary row, just by clicking on that row on the webpage. I also want to be able to retrieve the row index from that row as well. For example, if I would want to get the data from the first row, then I would get a 1 b

How would such a function look like?

1
  • Is it necessary for you to have getRowData() in the table element? Commented Mar 5, 2019 at 15:20

1 Answer 1

7

You have to place your click handler on the rows and not on the table.

Since your table is dynamically generated, attaching the click handlers from Typescript/JavaScript might be easier, here is a way to do it.

Use document.querySelector('#tableID') to get a reference to your table.

Then, there are two ways to get a reference to the table rows and cells:

  • Use table.querySelectorAll('tbody td') to query the rows in the table DOM. Then use row.querySelectorAll('td') to get the cells.

  • Use the table DOM API (see @H.B. comment below) to avoid querying the DOM for each row and each cell. With this technique you can get the rows with table.tBodies[0].rows and the cells with row.cells.

Then use element.addEventListener('click', handler) to attach the click handlers to every row.

Here is a JavaScript demo with detailed comments:

// get a reference to your table by id
// cast this to HTMLTableElement in TypeScript
const table = document.querySelector('#tableID');

// get all rows in the first table body
const rows = table.tBodies[0].rows;

// convert the rows to an array with the spread operator (...)
// then iterate over each row using forEach
Array.from(rows).forEach((row, idx) => {
  // attach a click handler on each row
  row.addEventListener('click', event => {
    // get all cells in the row, convert them to an array with the spread operator (...)
    // then for each cell, return its textContent by mapping on the array
    const tds = Array.from(row.cells).map(td => td.textContent);

    console.clear();
    // Log the row index
    console.log('row index:', idx);
    // Log the tds content array
    console.log('tds content:', ...tds);
    // join the contents of the tds with a space and display the string
    console.log('tds string:', tds.join(' '));
  });
});
<table id="tableID">
  <thead>
    <tr><th>From</th><th>Action</th><th>To</th></tr>
  </thead>
  <tbody>
    <tr><td>a</td><td>1</td><td>b</td></tr>
    <tr><td>a</td><td>0</td><td>a</td></tr>
  </tbody>
</table>

Also, in your TypeScript code, do not forget to cast the result of document.querySelector('#tableID') to HTMLTableElement to get the correct typing:

const table: HTMLTableElement = document.querySelector('#tableID');

See the TypeScript demo

Sign up to request clarification or add additional context in comments.

9 Comments

You could use the table DOM API, which i would prefer to always querying. I.e. to get rows => table.tBodies[0].rows, to get cells => row.cells. (In TypeScript you need to cast the result of the first query to HTMLTableElement.)
@H.B., Thank you for the comment, do you mind if I update my answer ?
Not at all, go ahead.
@jo_va when I try to follow your code example, I get the following error type <HTMLCollectionOf<HTMLTableRowElement> is not an array type when I try to use the spread operator, [...rows]. What should the type be?
@jo_va Thanks a lot, I think I found the mistake. I was targeting ES5 and not ES6.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.