skip to Main Content

I am trying to filter a table using plain JavaScript.

I have an input of type search and I filter the table rows by the value typed in that input.

function searchTable() {
  var input, filter, table, tr, tds, i, txt
  input = document.querySelector(".search-box")
  filter = input.value.toUpperCase()
  table = document.querySelector(".table-search")
  tr = table.querySelectorAll("tr")

  for (i = 0; i < tr.length; i++) {
    tds = Array.from(tr[i].getElementsByTagName("td"))

    if (tds.length) {
      tds.forEach(function(td) {
        txt = (td.textContent || td.innerText).toUpperCase()
        console.log(txt);
        if (!txt.includes(filter)) {
          console.log('hide')
          tr[i].classList.add("d-none")
        } else {
          console.log('show')
          tr[i].classList.remove("d-none")
        }
      })
    }
  }
}
.card-header {
  display: flex;
  align-items: center;
}

.search-box {
  border-color: #ccc !important;
  border-left: none;
  padding-left: 0;
}

.search-box:focus {
  box-shadow: none;
}

.btn-search {
  background: #fff !important;
  opacity: 1 !important;
  border-color: #ccc !important;
  border-right: none;
  padding-left: 10px;
  padding-right: 10px;
}

.table-heading {
  font-size: 1.25rem;
  font-weight: 700;
  margin: 0 15px 0 0;
  line-height: 1;
}

.table th {
  background: #f6f6f6;
}

.table > tbody > tr:nth-child(even of :not([class*="d-none"])) > td {
  background: #f6f6f6;
}

.sort-button {
  border-radius: 3px;
  background: #ccc;
  border: none;
}

.sort-button.active {
  background: #04aa6d;
  color: #fff;
}

.sort-button.desc {
  transform: rotateX(180deg);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />

<div class="container-fluid">
  <div class="card overflow-hidden shadow-sm my-2">
    <div class="card-header">
      <h2 class="table-heading">Users</h2>
      <div class="input-group input-group-prepend ms-auto w-75">
        <button class="btn btn-sm btn-search" type="button" disabled>
          <i class="fa-solid fa-magnifying-glass"></i>
        </button>
        <input type="search" class="form-control form-control-sm search-box" placeholder="Search" onkeyup="searchTable()" />
      </div>
    </div>
    <div class="card-body p-0">
      <table class="table table-search m-0">
        <thead>
          <tr>
            <th>Firstname</th>
            <th>Lastname</th>
            <th>Age</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td class="fname">Alan</td>
            <td class="lname">Green</td>
            <td class="age">24</td>
          </tr>
          <tr>
            <td class="fname">Anne</td>
            <td class="lname">Smith</td>
            <td class="age">42</td>
          </tr>
          <tr>
            <td class="fname">Jane</td>
            <td class="lname">Doe</td>
            <td class="age">19</td>
          </tr>
          <tr>
            <td class="fname">July</td>
            <td class="lname">Dooley</td>
            <td class="age">121</td>
          </tr>
          <tr>
            <td class="fname">Mary</td>
            <td class="lname">Moe</td>
            <td class="age">21</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Foe a reason I have not been able to spot, regardless of whether the search string mashes any results or not, all the rows are hidden.

Where is my mistake?

2

Answers


  1. The error is caused by checking each column and when the first matching column appears, but later the result does not match the second or third column, then the row is hidden again

    Here is a corrected code

    function searchTable() {
      var input, filter, table, tr, tds, i, txt, showRow;
      input = document.querySelector(".search-box");
      filter = input.value.toUpperCase();
      table = document.querySelector(".table-search");
      tr = table.getElementsByTagName("tr");
    
      for (i = 0; i < tr.length; i++) {
        tds = Array.from(tr[i].getElementsByTagName("td"));
        showRow = false; // variable to check whether to display the row
        if (tds.length) {
          tds.forEach(function(td) {
            txt = (td.textContent || td.innerText).toUpperCase();
            if (txt.includes(filter)) {
              showRow = true; // If a suitable cell is found, save the information
            }
          });
    
          if (showRow) {
            tr[i].classList.remove("d-none"); // If at least one cell matches, display the row
          } else {
            tr[i].classList.add("d-none"); // If not, hide
          }
        }
      }
    }
    
    Login or Signup to reply.
  2. This is because every time you go through a TD you hide or show the TR. This way, when you search for "Alan" and go through the TD "Alan" it shows the TR, but when you go through the next TD "GREEN" (from the Alan row) it hides the TR again.

    You can simply set a trShow flag to indicate whether the TR should be shown or not.

    function searchTable() {
      var input, filter, table, tr, tds, i, txt
      input = document.querySelector(".search-box")
      filter = input.value.toUpperCase()
      table = document.querySelector(".table-search")
      tr = table.getElementsByTagName("tr")
    
      for (i = 0; i < tr.length; i++) {
        var trShow = false;
        tr[i].classList.add("d-none")
        tds = Array.from(tr[i].getElementsByTagName("td"))
    
        if (tds.length) {
          tds.forEach(function(td) {
            txt = (td.textContent || td.innerText).toUpperCase()
            console.log(txt);
            if (!txt.includes(filter)) {
              console.log('hide')
              //tr[i].classList.add("d-none")
            } else {
              trShow = true;
              console.log('show')
              //tr[i].classList.remove("d-none")
            }
          })
        }
       if(trShow){
          tr[i].classList.remove("d-none")
       }
    
      }
    }
    .card-header {
      display: flex;
      align-items: center;
    }
    
    .search-box {
      border-color: #ccc !important;
      border-left: none;
      padding-left: 0;
    }
    
    .search-box:focus {
      box-shadow: none;
    }
    
    .btn-search {
      background: #fff !important;
      opacity: 1 !important;
      border-color: #ccc !important;
      border-right: none;
      padding-left: 10px;
      padding-right: 10px;
    }
    
    .table-heading {
      font-size: 1.25rem;
      font-weight: 700;
      margin: 0 15px 0 0;
      line-height: 1;
    }
    
    .table th {
      background: #f6f6f6;
    }
    
    .table > tbody > tr:nth-child(even of :not([class*="d-none"])) > td {
      background: #f6f6f6;
    }
    
    .sort-button {
      border-radius: 3px;
      background: #ccc;
      border: none;
    }
    
    .sort-button.active {
      background: #04aa6d;
      color: #fff;
    }
    
    .sort-button.desc {
      transform: rotateX(180deg);
    }
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" rel="stylesheet"/>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
    
    <div class="container-fluid">
      <div class="card overflow-hidden shadow-sm my-2">
        <div class="card-header">
          <h2 class="table-heading">Users</h2>
          <div class="input-group input-group-prepend ms-auto w-75">
            <button class="btn btn-sm btn-search" type="button" disabled>
              <i class="fa-solid fa-magnifying-glass"></i>
            </button>
            <input type="search" class="form-control form-control-sm search-box" placeholder="Search" onkeyup="searchTable()" />
          </div>
        </div>
        <div class="card-body p-0">
          <table class="table table-search m-0">
            <thead>
              <tr>
                <th>Firstname</th>
                <th>Lastname</th>
                <th>Age</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td class="fname">Alan</td>
                <td class="lname">Green</td>
                <td class="age">24</td>
              </tr>
              <tr>
                <td class="fname">Anne</td>
                <td class="lname">Smith</td>
                <td class="age">42</td>
              </tr>
              <tr>
                <td class="fname">Jane</td>
                <td class="lname">Doe</td>
                <td class="age">19</td>
              </tr>
              <tr>
                <td class="fname">July</td>
                <td class="lname">Dooley</td>
                <td class="age">121</td>
              </tr>
              <tr>
                <td class="fname">Mary</td>
                <td class="lname">Moe</td>
                <td class="age">21</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search