2

Here is an example code for table sorting taken from javascript.info: https://plnkr.co/edit/5xHStBMfV5AVtoxR?p=preview&preview=

let sortedRows = Array.from(table.tBodies[0].rows).sort((rowA, rowB) => rowA.cells[0].innerHTML.localeCompare(rowB.cells[0].innerHTML));

table.tBodies[0].append(...sortedRows);

My question is: Array.from(table.tBodies[0].rows) produces an array. But cells[0] is not defined for arrays. How does the code work?

2
  • rowA is a Row ... which has a .cells property Commented Sep 22, 2022 at 3:47
  • Why do you think it's not defined? Commented Sep 22, 2022 at 3:50

2 Answers 2

2

The .rows property of a table gives you an HTMLCollection of the rows in the table. Array.from turns the HTMLCollection of rows into an array of rows.

With

.sort((rowA, rowB) => rowA.cells[0] ...

Each parameter is one of the array items being iterated over - a row - neither rowA nor rowB are the array that was created with Array.from. They're the array elements, which are rows.

The array elements (which were originally the HTMLCollection elements) are still rows - and rows have a .cells property.

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

Comments

1

Your rowA is a TR, so you will have to use fetch cells from it. Array.from just converts an HTML collection/ NodeList to an Array of elements so that you can use Array methods

let sortedRows = Array.from(table.tBodies[0].rows)
  .sort((rowA, rowB) => {
    const cellsA = rowA.querySelectorAll('td')
    const cellsB = rowB.querySelectorAll('td')
    return cellsA[0].innerHTML.localeCompare(cellsB[0].innerHTML)
  });

table.tBodies[0].append(...sortedRows);
<table id="table">
<thead>
  <tr><th>Name</th><th>Surname</th><th>Age</th></tr>
</thead>
<tbody>
  <tr><td>John</td><td>Smith</td><td>10</td></tr>
  <tr><td>Pete</td><td>Brown</td><td>15</td></tr>
  <tr><td>Ann</td><td>Lee</td><td>5</td></tr>
  <tr><td>...</td><td>...</td><td>...</td></tr>
</tbody>
</table>

Data based approach:

const data = [
  { name: "John", surname: "Smith", age: 10},
  { name: "Pete", surname: "Brown", age: 15},
  { name: "Ann", surname: "Lee", age: 5},
]

const sortData = (key) => {
  return data
    .slice()
    .sort((a,b) => {
      return typeof a[key] === "string"
        ? a[key].localeCompare(b[key])
        : a[key] - b[key]
    });
}

const createTable = (data) => {
  return data.map((item) => {
    return `<tr>${
      Object.values(item)
      .map((value) => `<td>${value}</td>`)
      .join("")
    }</tr>`
  }).join("").concat("<tr><td>...</td><td>...</td><td>...</td></tr>")
}
const renderTable = (data) => {
  document
    .getElementById('table')
    .querySelector('tbody').innerHTML = createTable(data)
}

document
  .querySelector('.actionPanel')
  .addEventListener('click', (e) => {
    const text = e.target.textContent.toLowerCase();
    renderTable(sortData(text))
  })

renderTable(data)
<div class='actionPanel'>
  <button>Name</button>
  <button>Surname</button>
  <button>Age</button>
</div>
<table id="table">
  <thead>
    <tr><th>Name</th><th>Surname</th><th>Age</th></tr>
  </thead>
  <tbody></tbody>
</table>

1 Comment

An alternate would be to save data and generate table dynamically. That way, you need to sort data and recreate table. That is simpler and can also work on complex data/ conditions

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.