I've tried using the below js code to filter table rows. The code is originally from w3schools but I've done some modification to target all my input values. The filtering works great for one column but as fast as I try to input a value on a second column, it overwrites the previous filter.
For exampe if I filter for "Test" in column 1 it works great and hides the second row. If I after that also filter column 2 for id "2" it will hide the first row and instead display the second row for id 2. Is it possible to modify the code so that it only filters on the rows that are left and shown, not all the rows all together. Ive tried several hours trying to target only tr[i].style.display != "none"; but no success. My goal is something like this: DataTables. I've seen and read tons of other threads on here regarding this issue but nothing seems to work. Appreciate all the help and guidance.
| Name | ID |
|---|---|
| Test | 1 |
| Another test | 2 |
| [Input field for filter] | [Input field for filter] |
$(document).ready(function() {
document.querySelectorAll('.search').forEach(item => {
item.addEventListener('keyup', event => {
var input, filter, table, tr, td, i, txtValue;
input = event.target;
filter = input.value.toUpperCase();
table = document.getElementById("example");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[event.target.getAttribute('data-value')];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
})
})
} );
Your code was a mix of vanillaJS and jQuery, and tagged for both, so I went with jquery since it's a little more concise and easier to read.
Basically, you need to check both cells in each row against both search filters every time the key is pressed. To do so, I made things a tiny bit easier by giving the data TR rows a class so we're not searching the header or the cells with the search boxes. Then, I just compare filter 1 with cell 1 and filter 2 with cell 2 for each row. If there is a match for either, that row stays visible, otherwise it's hidden. I had to add in some logic in case there wasn't a value in either filter input.
Couple other notes:
$('.search').eq(0) is the same as the FIRST element with the class search$(el).find('td').eq(0).text().trim().toLowerCase() is the same as find the FIRST TD tag's text, trim off the extra whitespace and convert to lowercase$(document).ready(function() {
$('.search').keyup(function() {
let search1 = $('.search').eq(0).val().toLowerCase();
let search2 = $('.search').eq(1).val().toLowerCase();
$('.s-table tr.data').each(function(i, el) {
let val1 = $(el).find('td').eq(0).text().trim().toLowerCase()
let val2 = $(el).find('td').eq(1).text().trim().toLowerCase()
let ok = (search1 && val1.indexOf(search1) !== -1) || (search2 && val2.indexOf(search2) !== -1)
if (ok) $(el).closest('tr').show();
else $(el).closest('tr').hide();
})
return
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="s-table">
<thead>
<tr>
<th>Name</th>
<th>ID</th>
</tr>
</thead>
<tbody>
<tr class='data'>
<td>Test</td>
<td>1</td>
</tr>
<tr class='data'>
<td>Another test</td>
<td>2</td>
</tr>
<tr>
<td><input data-col='0' class='search' placeholder='filter'></td>
<td><input data-col='1' class='search' placeholder='filter'></td>
</tr>
</tbody>
</table>