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
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
This is because every time you go through a
TD
you hide or show theTR
. This way, when you search for "Alan" and go through theTD
"Alan" it shows theTR
, but when you go through the nextTD
"GREEN" (from the Alan row) it hides theTR
again.You can simply set a
trShow
flag to indicate whether theTR
should be shown or not.