Search code examples
javascripthtmldomhtml-tableinnerhtml

Unable to asign value to a table row using innerHTML


I have this script to sort all the tr by number and all seems to work, but when its time to assign the new values using innerHTML to each table row then the array with the sorted table rows start changing its value randomly evertime a value is assign to a row and I don't know why:

Heres the code:

Run the snippet to see what I mean and thanks.

"use strict"

let table = document.getElementById("grid");
let tableHead = table.querySelector("thead");

tableHead.addEventListener("click",event=>{
    let tbody = table.getElementsByTagName("tbody")[0];
    let rows = tbody.getElementsByTagName("tr");
    let arr = null;

    switch(event.target.dataset.type) {
        case "number":
            arr = Array.from(rows).sort((a,b)=>{
                return +a.firstElementChild.innerHTML > +b.firstElementChild.innerHTML ? 1: -1;
            });
            break;
        case "string":
            break;
    }
   

for(let i = 0; i < rows.length; i++) {
    console.log(rows[i].innerHTML,"rows");//Shows the current order
}
for(let i = 0; i < arr.length;i++) {
    console.log(arr[i].innerHTML,"arr"); //Shows the sorted table rows as expected
}

for(let i = 0; i < arr.length;i++) {
    rows[i].innerHTML = arr[i].innerHTML; //But now arr have randoms values!!
}
});
table{
    border: 1px solid black;
    border-spacing: 0px;
}
td, th{
    border: 1px solid rgb(0, 0, 0);
    margin: 0px;
    padding: 0.5rem;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Title</title>
</head>
<body>
    <table id="grid">
    <thead>
      <tr>
        <th data-type="number">Age</th>
        <th data-type="string">Name</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>5</td>
        <td>John</td>
      </tr>
      <tr>
        <td>2</td>
        <td>Pete</td>
      </tr>
      <tr>
        <td>12</td>
        <td>Ann</td>
      </tr>
      <tr>
        <td>9</td>
        <td>Eugene</td>
      </tr>
      <tr>
        <td>1</td>
        <td>Ilya</td>
      </tr>
    </tbody>
  </table>

    <script src="script.js"></script>
</body>
</html>


Solution

  • This is because both rows and arr arrays contain the same element objects, so changing element in one array changes it in another. In this particular case you can simply append rows to tbody instead:

    "use strict"
    
    let table = document.getElementById("grid");
    let tableHead = table.querySelector("thead");
    
    tableHead.addEventListener("click",event=>{
        let tbody = table.getElementsByTagName("tbody")[0];
        let rows = tbody.getElementsByTagName("tr");
        let arr = null;
    
        switch(event.target.dataset.type) {
            case "number":
                arr = Array.from(rows).sort((a,b)=>{
                    return +a.firstElementChild.innerHTML > +b.firstElementChild.innerHTML ? 1: -1;
                });
                break;
            case "string":
                break;
        }
       
    
    for(let i = 0; i < rows.length; i++) {
        console.log(rows[i].innerHTML,"rows");//Shows the current order
    }
    for(let i = 0; i < arr.length;i++) {
        console.log(arr[i].innerHTML,"arr"); //Shows the sorted table rows as expected
    }
    
    for(let i = 0; i < arr.length;i++) {
        tbody.appendChild(arr[i]);
    //    rows[i].innerHTML = arr[i].innerHTML; //But now arr have randoms values!!
    }
    });
    table{
        border: 1px solid black;
        border-spacing: 0px;
    }
    td, th{
        border: 1px solid rgb(0, 0, 0);
        margin: 0px;
        padding: 0.5rem;
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="style.css">
        <title>Title</title>
    </head>
    <body>
        <table id="grid">
        <thead>
          <tr>
            <th data-type="number">Age</th>
            <th data-type="string">Name</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>5</td>
            <td>John</td>
          </tr>
          <tr>
            <td>2</td>
            <td>Pete</td>
          </tr>
          <tr>
            <td>12</td>
            <td>Ann</td>
          </tr>
          <tr>
            <td>9</td>
            <td>Eugene</td>
          </tr>
          <tr>
            <td>1</td>
            <td>Ilya</td>
          </tr>
        </tbody>
      </table>
    
        <script src="script.js"></script>
    </body>
    </html>