retro_coder
retro_coder

Reputation: 456

How to filter/search columns in HTML table?

I have followed this link on how to create/filter search a table. But I want to filter search for each column in my own table. Currently, it only searches for the First Name column. How can I do this?

This is the code:

myHTML:

<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">

<table id="myTable">
    <tr class="header">
        <th> First Name </th>
        <th> Last Name </th> 
        <th> Age </th>
        <th> Language </th>
    </tr>
    <tr>
        <td>John</td>
        <td>Kole</td>
        <td>18</td>
        <td>English</td>
    </tr>
    <tr>
        <td>Pearl</td>
        <td>Shine</td>
        <td>50</td>
        <td>Hindi</td>
    </tr>
   <tr>
        <td>Jacob</td>
        <td>Pool</td>
        <td>22</td>
        <td>Arabic</td>
   </tr>
   <tr>
        <td>David</td>
        <td>Struff</td>
        <td>30</td>
        <td>German</td>
   </tr>
</table>

<script>
    function myFunction() {
        var input, filter, table, tr, td, i, txtValue;
        input = document.getElementById("myInput");
        filter = input.value.toUpperCase();
        table = document.getElementById("myTable");
        tr = table.getElementsByTagName("tr");
        for (i = 0; i < tr.length; i++) {
            td = tr[i].getElementsByTagName("td")[0];
            if (td) {
                txtValue = td.textContent || td.innerText;
                if (txtValue.toUpperCase().indexOf(filter) > -1) {
                    tr[i].style.display = "";
                    }
                else {
                    tr[i].style.display = "none";
                    }
                }       
            }
        }
</script>

How can I filter all columns for searching? Currently, it searches the First Name column only.

Upvotes: 0

Views: 3846

Answers (3)

user3589620
user3589620

Reputation:

Get all table rows. Loop through these rows. Put all the innerText from the <td>s in each row together into a string. Check the first occurrence of the search value in the string. If the value is not found, hide the row with display: none else show the row with display: table-row.

Example

const id = "myTable";
const selector = `#${id} tr:not(.header)`;
// Get all rows
const trs = document.querySelectorAll(selector);

function myFunction(event) {
  let search = event.target.value.toLowerCase();

  trs.forEach((tr) => {
    // Get all cells in a row
    let tds = tr.querySelectorAll("td");

    // String that contains all td textContent from a row
    let str = Array.from(tds).map((td) => {
      return td.textContent.toLowerCase();
    }).join("");

    tr.style.display = (str.indexOf(search) > -1) ? "table-row" : "none";
  });
}
<input type="text" id="myInput" onkeyup="myFunction(event)" placeholder="Search for names.." title="Type in a name">

<table id="myTable">
  <tr class="header">
    <th> First Name </th>
    <th> Last Name </th>
    <th> Age </th>
    <th> Language </th>
  </tr>
  <tr>
    <td>John</td>
    <td>Kole</td>
    <td>18</td>
    <td>English</td>
  </tr>
  <tr>
    <td>Pearl</td>
    <td>Shine</td>
    <td>50</td>
    <td>Hindi</td>
  </tr>
  <tr>
    <td>Jacob</td>
    <td>Pool</td>
    <td>22</td>
    <td>Arabic</td>
  </tr>
  <tr>
    <td>David</td>
    <td>Struff</td>
    <td>30</td>
    <td>German</td>
  </tr>
</table>

Upvotes: 0

Nitheesh
Nitheesh

Reputation: 19986

Check each nodes of the table row instead of just checking tr[i].getElementsByTagName("td")[0]. The zeroth node corresponds to first name field, that's why the search result restricts to the first name field only.. Search for all the nodes instead.

Leave the tr node with class name of header while making the row hidden.

function myFunction() {
    var input, filter, table, tr, td, i, txtValue;
    input = document.getElementById("myInput");
    filter = input.value.toUpperCase();
    table = document.getElementById("myTable");
    tr = table.getElementsByTagName("tr");
    for (i = 0; i < tr.length; i++) {
        // td = tr[i].getElementsByTagName("td")[0];
        alltags = tr[i].getElementsByTagName("td");
        isFound = false;
        for(j=0; j< alltags.length; j++) {
          td = alltags[j];
          if (td) {
              txtValue = td.textContent || td.innerText;
              if (txtValue.toUpperCase().indexOf(filter) > -1) {
                  tr[i].style.display = "";
                  j = alltags.length;
                  isFound = true;
              }
            }       
          }
          if(!isFound && tr[i].className !== "header") {
            tr[i].style.display = "none";
          }
        }
    }
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">

<table id="myTable">
    <tr class="header">
        <th> First Name </th>
        <th> Last Name </th> 
        <th> Age </th>
        <th> Language </th>
    </tr>
    <tr>
        <td>John</td>
        <td>Kole</td>
        <td>18</td>
        <td>English</td>
    </tr>
    <tr>
        <td>Pearl</td>
        <td>Shine</td>
        <td>50</td>
        <td>Hindi</td>
    </tr>
   <tr>
        <td>Jacob</td>
        <td>Pool</td>
        <td>22</td>
        <td>Arabic</td>
   </tr>
   <tr>
        <td>David</td>
        <td>Struff</td>
        <td>30</td>
        <td>German</td>
   </tr>
</table>

Hope this is what you are looking for.

Upvotes: 3

arm
arm

Reputation: 136

This line:

td = tr[i].getElementsByTagName("td")[0];

gets the first td which is the content for the first column in the table meaning the FirstName column. Do a loop on all td tags instead of getting only the first one and you'll get the functionality you need.

Upvotes: 0

Related Questions