I have a table with pagination and a search function that searches the said table. At the moment the search function only searches for values on the table page I am on rather than the entire table. Is there any way I can amend the search function below to allow the entire table to be searched?
Please note I am searching by multiple TD elements of the table so hence the multiple TD variables.
TS File
searchTable(table) {
var input, filter, table, tr, td, td2, td3, td4, i, txtValue, txtValue2, txtValue3, txtValue4;
input = document.getElementById("searchInput");
filter = input.value.toUpperCase();
table = document.getElementById(table);
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
td2 = tr[i].getElementsByTagName("td")[1];
td3 = tr[i].getElementsByTagName("td")[2];
td4 = tr[i].getElementsByTagName("td")[3];
if (td || td2 || td3 || td4) {
txtValue = td.textContent || td.innerText;
txtValue2 = td2.textContent || td2.innerText;
txtValue3 = td3.textContent || td3.innerText;
txtValue4 = td4.textContent || td4.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1 || txtValue2.toUpperCase().indexOf(filter) > -1 || txtValue3.toUpperCase().indexOf(filter) > -1 || txtValue4.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
Table
<table class="table align-items-center table-flush" id="customersTable">
<thead class="thead-light">
<tr>
<th scope="col">Name</th>
<th scope="col">Contact Email</th>
<th scope="col">Package</th>
<th scope="col">Subscription</th>
<th scope="col">Active</th>
<th scope="col">Customer Since</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let cust of customers | slice: (page-1) * pageSize : (page-1) * pageSize + pageSize">
<td class="primaryColumn">
{{cust.name.S}}
</td>
<td>
{{cust.email.S}}
</td>
<td>
{{cust.package_name.S}}
</td>
<td>
{{cust.subscription_name.S}}
</td>
<td [ngClass]="{
'active' : cust.sub_status.BOOL == true,
'inactive' : cust.sub_status.BOOL == false
}">
{{cust.sub_status.BOOL}}
</td>
<td>
{{cust.date_created.S}}
</td>
<td class="text-right">
<div ngbDropdown placement="bottom-right">
<a class="btn btn-sm btn-icon-only text-light" ngbDropdownToggle>
<i class="fas fa-ellipsis-v"></i>
</a>
<div ngbDropdownMenu class=" dropdown-menu-right dropdown-menu-arrow">
<a class="dropdown-item" (click)="selectCustomer(cust);openForm(custUpdate)"><i class="fas fa-edit"></i><span class="menu-option">Edit</span></a>
<a class="dropdown-item" (click)="selectCustomer(cust);openForm(custDelete)"><i class="fas fa-trash"></i><span class="menu-option">Delete</span></a>
</div>
</div>
</td>
</tr>
</tbody>
</table>
HTML File
<div class="form-group has-search">
<span class="fa fa-search form-control-feedback"></span>
<input type="text" id="searchInput" class="form-control" placeholder="Search" (keyup)="searchTable('customersTable')">
</div>
Thanks all!
Since pagination is done on the front-end side and since, as someone also stated in the comments section, this is an Angular application, juggling with DOM is not the best practice.
What you can do is use a work variable that would hold the current state of the customers list at any time and hold the data set in a different variable.
Table filtering would mean filtering the complete data set and assigning the result to the work variable. Angular should then detect the change and update the DOM accordingly.
Related
I have a table called myTable which displays a list of files. I then have a dropdown box and a search box.
All of this functionality works, if i search for a PO no, and if i select a vendor - this all works fine.
I want to amend my JS code for the search box to check if the dropdown is populated, and if it is then take that into consideration when searching for a PO no.
My cshtml code is as follows:
<h1 style="color: white">Purchase Orders</h1>
<p>
<a asp-page="Create" style="color:white">Create File</a>
</p>
<div class="row">
<div class="col-sm-12">
<div class="form-check-inline pull-right">
<label style="color:white">Search</label>
<input type="text" class="form-control" id="myInput" placeholder="Search Purchase Orders..." onkeyup="myFunction()" />
</div>
<select asp-items="#((List<SelectListItem>)ViewData["test"])" id="vendor" onchange="myFunctionThree()">
<option value="" disabled selected> Select a Vendor</option>
</select>
<input class="btn btn-light" value="Clear All Filters" onclick="history.go(0)" style="float: right">
<table class="table" style="background-color: white" id="myTable">
<thead>
<tr class="header">
<th>
PO No.
</th>
<th>
Haulier
</th>
<th>
Comments
</th>
<th>
Vendor
</th>
<th>
Upload
</th>
<th>
Date Uploaded
</th>
<th>Download</th>
<th>Delete Attachment</th>
<th>Notify</th>
<th>Sent</th>
<th>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Files)
{
if (item.FileType == "Purchase Order")
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Number)
</td>
<td>
#Html.DisplayFor(modelItem => item.Haulier)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comments)
</td>
<td>
#Html.DisplayFor(modeItem => item.Vendor.VendorName)
</td>
<td>
<a asp-page="Upload" asp-route-id="#item.Id">Upload File Attachment</a>
</td>
<td>
#Html.DisplayFor(modelItem => item.UploadDate)
</td>
<td>
#if (item.Attachment != null)
{
<form asp-page-handler="Download" method="post" asp-route-id="#item.Id">
<input type="submit" class="btn btn-dark" value="Download">
</form>
}
</td>
<td>
#if (item.Attachment != null)
{
<form asp-page-handler="Delete" method="post" asp-route-id="#item.Id">
<input type="submit" class="btn btn-danger" value="Delete Attachment">
</form>
}
</td>
<td>
#if (item.Attachment != null)
{
<form asp-page-handler="Email" method="post" asp-route-id="#item.Id">
<input type="submit" class="btn btn-danger" value="Notify Vendor">
</form>
}
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailSent)
</td>
<td>
<a asp-page="/Admin/Details" asp-route-id="#item.Id">Details</a>
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
<script>
//function for search bar
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
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";
}
}
}
}
}
//function for dropdown menu
function myFunctionThree()
{
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("vendor");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[3];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
I am not too familiar with js, so if someone could point me in the right direction please.
If you need any further info lmk.
After some tinkering around with the code, I found a solution that works.
Finalised code(for search bar script):
//function for search bar
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i, txtValue, dropdownValue, dropdownInput, dtd;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
dropdownInput = document.getElementById("vendor");
dropdownValue = dropdownInput.value.toUpperCase();
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
dtd = tr[i].getElementsByTagName("td")[3];
if (td) {
txtValue = td.textContent || td.innerText;
dropTxtValue = dtd.textContent || dtd.innerText;
if(dropdownValue == ""){
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
else{
if((txtValue.toUpperCase().indexOf(filter) > -1) && (dropTxtValue.toUpperCase().indexOf(dropdownValue) > -1)){
tr[i].style.display = "";
}else{
tr[i].style.display = "none";
}
}
}
}
}
I have a query regarding javascript. I am working on a structure with nested tables and rows (tr) are in the loop and inside it (td) are also in the loop. I want to compare the data of 2 columns one outside the loop and one td inside the loop and in case of a match would like to highlight the td outside the loop. Here is a piece of code that I wrote but it is highlighting all the rows rather than only the corresponding one. Also, it's not running on all the td which are inside the for-loop.
function highlight_text(){
table = document.getElementById("table");
tr = table.getElementsByClassName("rows");
for (x = 0; x < tr.length; x++) {
td = tr[x].getElementsByTagName("td")[3];
txtValue = td.textContent || td.innerText;
txtValue = txtValue.trim()
search_text = tr[x].getElementsByTagName("td")[5];
search_value = search_text.textContent || search_text.innerText
search_value = search_value.trim()
if (txtValue.toUpperCase().indexOf(search_value.toUpperCase()) > -1) {
const regex = new RegExp(search_value,"gi");
let text = tr[x].getElementsByTagName("td")[3].innerHTML;
text = text.replace(/(<mark>|<\/mark>)/gim, '');
text = text.replace(regex, '<mark>$&</mark>')
td.innerHTML = text
}
}
}
<table id="table" style="border: none;">
{% for a in range(respondent_id|length) %}
<tr class="rows">
<td class="c1" colspan="2"><b>{{ Score[a] }}</b></td>
<td><span style="display:none;" id="id_resp">{{ respondent_id[a] }}</span></td>
<td>
<table width="980px;" style="border-color:white;">
<tr>
<td class="verb">{{ Verbatim_data[a] }}</td>
</tr>
</table>
<table>
<tr>
{% for w in range(Final_L1L2L3|length) %}
<td class="L3_comment" onclick="highlight_text()"><div>{{Final_L1L2L3[w] | safe}} </div></td>
<td style="display: none;" class="search">{{Final_verb[w] | safe}}</td>
{% endfor %}
</tr>
</table>
</td>
</tr>
{{endfor}}
</table>
enter image description here
I have a dynamic table that I am displaying in the front end like this:
<table id ="tblRE">
<tr class="row">
<th ng-repeat="column in cols_re">{{column}}</th>
</tr>
<tr ng-repeat="row in data['dict_re']">
<td ng-repeat="column in cols_re">{{row[column]}}</td>
</tr>
</table>
I want to put a filter on one of the columns named OUT(my 2nd column from the table).
If I would have a fix column name I would do like this:
<tr class="row">
<td class="head" ng-click="sortData='OUT';sortOrder=!sortOrder"> OUT</td>
</tr>
<tr ng-repeat="item in data.table_df| orderBy:sortData:sortOrder | filter:filter ">
<td>{{ item.OUT}}</td>
</tr>
Is there an option on how I can put the filter with my initial option?
I also tried to add a search button which kind of works only for the first column. I want to be able to filter also on the second column.
The code for the search button:
js:
function searchre() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("tblRE");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
and in HTML:
<input class="myInput" type="text" id="myInput" onkeyup="searchre()" placeholder="Search.." title="Type in a name">
Any idea on how I can filter on the first and 2nd column?
I have here a search bar where I can search employee onkeyup event. But When i try to add class and another td tag then the function is not working. Please see my code below. Any help would be much appreciated. Thank you!
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("search2");
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";
}
}
}
}
<table id="myTable">
<tr>
<td class="imageindent">
<img src="img.jpg" border="1" style="border-color:#CCCCCC" />
</td>
<td class="gentext" id="empname"> JOHN BRYAN SMITH <span class="textCapitalized"></span>
<span class="textCapitalized">
Gray<br />JohnSMith#gmail.com <br />
</span>
</td>
<td class="gentext"><span class="texblue">JUNIOR PRODUCER</span>/<br />EVENTS</td>
<td width="120" class="title2">2114</td>
</tr>
</table>
<input name="search" type="text" class="textsimple" id="search2" onkeyup="myFunction()" />
This is how you'd do it using modern Javascript. Let me know if anything is unclear, so I can explain in detail.
As a sidenote: Every tr "knows" it's tds and has stored them in an HTMLCollection called cells.
search2.addEventListener('input', () => {
myTable.querySelectorAll('tr').forEach(row => row.hidden = row.cells[1].innerText.toUpperCase().indexOf(search2.value.toUpperCase()) === -1)
})
<table id="myTable">
<tr>
<td class="imageindent">
<img src="img.jpg" border="1" style="border-color:#CCCCCC" />
</td>
<td class="gentext"> JOHN BRYAN SMITH <span class="textCapitalized"></span>
<span class="textCapitalized">
Gray<br />JohnSMith#gmail.com <br />
</span>
</td>
<td class="gentext"><span class="texblue">JUNIOR PRODUCER</span>/<br />EVENTS</td>
<td width="120" class="title2">2114</td>
</tr>
<tr>
<td class="imageindent">
<img src="img.jpg" border="1" style="border-color:#CCCCCC" />
</td>
<td class="gentext"> JACK BRUCE <span class="textCapitalized"></span>
<span class="textCapitalized">
Gray<br />JackBruce#gmail.com <br />
</span>
</td>
<td class="gentext"><span class="texblue">JUNIOR PRODUCER</span>/<br />EVENTS</td>
<td width="120" class="title2">2114</td>
</tr>
</table>
<input name="search" type="text" class="textsimple" id="search2" />
Changed this line td = tr[i].getElementsByTagName("td")[1]; to use index [1] since you need the second td. The index [0] referred to the first TD. I recommend to use some class selector to get the right td since that is more reliable when the table structure changes.
Also you use an id in one of your td's (id="empname"). I assume you can get multiple rows. If so you need to make sure this id is unique. It's better to not use id's in dynamic content but classes instead.
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("search2");
filter = input.value.toUpperCase();
console.log(filter);
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
if (td) {
txtValue = td.textContent || td.innerText;
console.log(txtValue);
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
<table id="myTable">
<tr>
<td class="imageindent">
<img src="img.jpg" border="1" style="border-color:#CCCCCC" />
</td>
<td class="gentext" id="empname"> JOHN BRYAN SMITH <span class="textCapitalized"></span>
<span class="textCapitalized">
Gray<br />JohnSMith#gmail.com <br />
</span>
</td>
<td class="gentext"><span class="texblue">JUNIOR PRODUCER</span>/<br />EVENTS</td>
<td width="120" class="title2">2114</td>
</tr>
</table>
<input name="search" type="text" class="textsimple" id="search2" onkeyup="myFunction()" />
In my code i use fnFilter function of Jquery datatable to search the data.
In some cases it search perfectly but in some cases it not.
if i try to search code = "BS" it will search perfectly.
But when i try to search using code = "AL" it will display all records. which is not correct.
This is my code for datatable search option.
$("div.dataTables_filter input").bind('keypress', function (e) {
var searchText = $(this).val().trim();
if (e.which == 13) {
$("#search-error-text").remove();
if (searchText.length > 0) {
var value = searchText;
oTable.fnFilter(value);
$("div.dataTables_filter input").val(searchText);
}
else {
var errorMessage = "Please Enter Data!";
$("div.dataTables_filter input").before("<span id='search-error-text' class='error-text'>" + errorMessage + "</span>");
return;
}
}
else {
return;
}
});
$("div.dataTables_filter #grid-search-button").click(function () {
$("#search-error-text").remove();
var searchText = $("div.dataTables_filter input").val().trim();
if (searchText.length > 0) {
var value = searchText;
oTable.fnFilter(value);
$("div.dataTables_filter input").val(searchText);
}
else {
var errorMessage = "Please Enter Data!";
$("div.dataTables_filter input").before("<span id='search-error-text' class='error-text'>" + errorMessage + "</span>");
return false;
}
});
Html code below table.
<div class="table-responsive">
<table id="datatable-sale" class="datatable">
<thead>
<tr>
<th class="table_heading table-head ">
Code
</th>
<th class="table_heading table-head">
Description
</th>
<th class="table_heading table-head">
Type
</th>
<th class="table_heading table-head cursorDefault">
Edit
</th>
<th class="table_heading table-head cursorDefault">
Status
</th>
<th class="table_heading table-head cursorDefault">
Delete
</th>
</tr>
</thead>
<tbody class="table-head">
#foreach (var item in ViewData["sale"] as IEnumerable<Sales_lut>)
{
<tr>
<td class="table_heading text-left table-head-maintenance Width-10">
#item.code
</td>
<td class="table_heading text-left">
#item.descrip
</td>
<td class="table_heading text-left table-head-maintenance Width-10">
#item.type1
</td>
<td class="table_heading">
<a id="edit_sale" href="#" class=" edit action-button permission-based-access" saleidval="#item.saleid" permission-key="#Permissions.Sale.GetText()" sale-code="#item.code">
<i class="icon-pencil input-icon success" title="Edit">
</i>
</a>
</td>
<td class="table_heading permission-based-access" permission-key="#Permissions.Sale.GetText()">
#if (item.status == 0)
{
<a class="active" href="" title="Change Status" active-id="#item.saleid" sale-code="#item.code" active-code="#item.code">
<img id="active" src="#Url.Content("~/Content/Images/tick.png")" />
</a>
}
else
{
<a class="in-active" href="" title="Change Status" in-active-id="#item.saleid" sale-code="#item.code" in-active-code="#item.code">
<img id="in-active" src="#Url.Content("~/Content/Images/bullet_cross.png")" />
</a>
}
</td>
<td class="table_heading">
<a id="delete_sale" class=" deletesale delete permission-based-access" permission-key="#Permissions.Sale.GetText()" href="#" sale-code="#item.code">
<i class="icon-trash" title="delete">
</i>
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
Attach screenshot display an actual issue.Code "FZ" and "AM" does not contain any word as "AL" then also it display this records. and this happen for multiple search options. I need to apply search for whole data so i can't use single column search option.I just find out one issue that it search alternate rows means it search only odd rows in the grid. Any solution for it ???