How to search based on multiple column using basic jQuery - javascript

I am working on table layout with search on top of each row.
https://codepen.io/chiragjain94/pen/rNLBbNG
I want to search for "897" in first column and in second column I want to enter "Card"
The result should be => 553492-987 897 Traveller Card
But that is not the result I get.
$(document).on('input', '.filter-table', function() {
var searchKey = $(this).val().toLowerCase();
var tableName = $(this).attr('data-table-id');
var columnId = $(this).attr('data-column-id');
$("#" + tableName + " tbody td:nth-child(" + columnId + ")").filter(function() {
$(this).parent().toggle($(this).text().toLowerCase().indexOf(searchKey) > -1);
});
});
<table class="table mb-0 table-striped" id="selectedList">
<thead>
<tr>
<td colspan="2">Table</td>
</tr>
<tr class="search-fields" style="">
<td><input type="search" class="form-control search-input filter-table valid" data-table-id="selectedList" data-column-id="1" placeholder="Search column 1..." autocomplete="off"></td>
<td><input type="search" class="form-control search-input filter-table" data-table-id="selectedList" data-column-id="2" placeholder="Search column 2" autocomplete="off"></td>
</tr>
</thead>
<tbody>
<tr class="search-row">
<td>Card 126 897</td>
<td>Big Bank 2015</td>
</tr>
<tr class="search-row">
<td>553492-987 897</td>
<td>Traveller Card</td>
</tr>
<tr class="search-row" style="">
<td>Card 67920</td>
<td>Credit Card 8729
</td>
</tr>
</tbody>
</table>
Additional condition, once I clear any of the search input, my result table should still show result based on other search input.

Instead of filtering by comparing each input value separately, you should take both in account. You can do it this way:
$(document).on('input', '.filter-table', function () {
var tableName = $(this).attr('data-table-id');
var searchKey1 = $("[data-column-id='1']").val().toLowerCase();
var searchKey2 = $("[data-column-id='2']").val().toLowerCase();
$("#" + tableName + " tbody tr").filter(function () {
var columnSearch1 = !searchKey1 ||
$(this).children().eq(0).text().toLowerCase().indexOf(searchKey1) > -1;
var columnSearch2 = !searchKey2 ||
$(this).children().eq(1).text().toLowerCase().indexOf(searchKey2) > -1;
$(this).toggle(columnSearch1 && columnSearch2);
});
});
Link to example

Related

Get summary number from only visible table rows

I have a code which counts a total summary of all price table cells. This is not exactly what do I need. I need to count the summary from only visible rows. I use filtering by date range, once I change date it displays only dates from the selected date range, but the summary price is from the all rows. I need to implement the part of the code for visible table rows only and update the summary price in the span.
Any advice?
function filterRows() {
var from = jQuery("#datefilterfrom").val();
var to = jQuery("#datefilterto").val();
if (!from && !to) { // no value for from and to
return;
}
from = from || "1970-01-01"; // default from to a old date if it is not set
to = to || "2999-12-31";
var dateFrom = moment(from);
var dateTo = moment(to);
jQuery("#table tr").each(function(i, tr) {
var val = jQuery(tr).find("td:nth-child(2)").text();
var dateVal = moment(val, "DD.MM.YYYY");
var visible = (dateVal.isBetween(dateFrom, dateTo, null, [])) ? "" : "none"; // [] for inclusive
jQuery(tr).css("display", visible);
//summary start
var table = document.getElementById("table"),
sumVal = 0;
for (var i = 1; i < table.rows.length; i++) {
sumVal = sumVal + parseInt(table.rows[i].cells[2].innerHTML);
}
document.getElementById("val").innerHTML = "Sum Value = " + sumVal;
console.log(sumVal);
});
//summary end
}
jQuery("#datefilterfrom").on("change", filterRows);
jQuery("#datefilterto").on("change", filterRows);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<div class="row">
<div class="col-md-3">
<h4>Date from</h4>
<input type="date" class="form-control" id="datefilterfrom" data-date-split-input="true">
<h4>Date to</h4>
<input type="date" class="form-control" id="datefilterto" data-date-split-input="true">
</div>
</div>
<span id="val"></span>
<table id="table" class="sortable">
<tr>
<th>Name</th>
<th>Date</th>
<th>Price</th>
</tr>
<tr>
<td>Name</td>
<td>20.10.2020</td>
<td>20</td>
</tr>
<tr>
<td>Name</td>
<td>21.10.2020</td>
<td>25</td>
</tr>
<tr>
<td>Name</td>
<td>22.10.2020</td>
<td>30</td>
</tr>
</table>
This is how it looks like when I select date range in HTML (so I need to get summary from only this selected tr)
I think there need to be some condition added here
sumVal = sumVal + parseInt(table.rows[i].cells[2].innerHTML);
You don't need two loops. You're already looping through the rows with .each() to make them visible or invisible, you can calculate the total in that same loop. After you determine if the row should be visible, use that variable in an if statement to add to the total.
jQuery has a built-in function .toggle() that will switch the visibility of an element. You can make visible a boolean variable instead of a display style value, then use that as the argument to .toggle(). Then you can use this same value in the if condition.
Make your access to columns less dependent on the table layout by using classes instead of column indexes. Use jQuery(tr).find(".price") to access the price column, for instance.
Use <thead> and <tbody> to distinguish the headings from the table data, then use tbody in the .each() loop to only process data rows.
function filterRows() {
var from = jQuery("#datefilterfrom").val();
var to = jQuery("#datefilterto").val();
if (!from && !to) { // no value for from and to
return;
}
from = from || "1970-01-01"; // default from to a old date if it is not set
to = to || "2999-12-31";
var dateFrom = moment(from);
var dateTo = moment(to);
var sumVal = 0;
jQuery("#table tbody tr").each(function(i, tr) {
var val = jQuery(tr).find(".date").text();
var dateVal = moment(val, "DD.MM.YYYY");
var visible = (dateVal.isBetween(dateFrom, dateTo, null, []));
jQuery(tr).toggle(visible);
if (visible) {
sumVal += parseInt(jQuery(tr).find(".price").text());
}
$("#val").text("Sum Value = " + sumVal);
});
}
jQuery("#datefilterfrom, #datefilterto").on("change", filterRows);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<div class="row">
<div class="col-md-3">
<h4>Date from</h4>
<input type="date" class="form-control" id="datefilterfrom" data-date-split-input="true">
<h4>Date to</h4>
<input type="date" class="form-control" id="datefilterto" data-date-split-input="true">
</div>
</div>
<span id="val"></span>
<table id="table" class="sortable">
<thead>
<tr>
<th>Name</th>
<th>Date</th>
<th>Price</th>
</tr>
<thead>
<tbody>
<tr>
<td>Name</td>
<td class="date">20.10.2020</td>
<td class="price">20</td>
</tr>
<tr>
<td>Name</td>
<td class="date">21.10.2020</td>
<td class="price">25</td>
</tr>
<tr>
<td>Name</td>
<td class="date">22.10.2020</td>
<td class="price">30</td>
</tr>
<tbody>
</table>

My validation does not work on added rows and autonumbering

I have a function where i can add rows and autonumbering. The add rows works when you click the "add row" button, and auto numbering works when you press Ctrl+Enter key when there's 2 or more rows. My problem is, my validation does not work on my autonumbering.
For example: when I type manually the "1" on the textbox, it works.
But when I do my auto numbering, "Not good" does not appear on my 2nd
textbox.
Is there anything I missed? Any help will be appreciated.
//this is for adding rows
$("#addrow").on('click', function() {
let rowIndex = $('.auto_num').length + 1;
let rowIndexx = $('.auto_num').length + 1;
var newRow = '<tr><td><input class="auto_num" type="text" name="entryCount" value="' + rowIndexx + '" /></td>"' +
'<td><input name="lightBand' + rowIndex + '" value="" class="form" type="number" /> <span class="email_result"></span></td>"' +
'<td><input type="button" class="removerow" id="removerow' + rowIndex + '" name="removerow' + rowIndex + '" value="Remove"/></td>';
$("#applicanttable > tbody > tr:last").after(newRow);
});
//this is for my validation
$(document).on('change', 'input[name*=lightBand]', function() {
var lightBand1 = $(this).val(); //get value
var selector = $(this) //save slector
selector.next('.email_result').html("") //empty previous error
if (lightBand1 != '') {
/*$.ajax({
url: "<?php echo base_url(); ?>participant/check_number_avalibility",
method: "POST",
data: {
lightBand1: lightBand1
},
success: function(data) {*/
selector.next('.email_result').html("NOT GOOD"); //use next here ..
/* }
});*/
}
});
// this is for autonumbering when ctrl+enter is pressed.
const inputs = document.querySelectorAll(".form");
document.querySelectorAll(".form")[0].addEventListener("keyup", e => {
const inputs = document.querySelectorAll(".form");
let value = parseInt(e.target.value);
if ((e.ctrlKey || e.metaKey) && (e.keyCode == 13 || e.keyCode == 10)) {
inputs.forEach((inp, i) => {
if (i !== 0) {
inp.value = ++value;
}
})
}
});
Add a row and type any number at number textbox column and press ctrl+enter. You'll see the "Not good" is not working on added rows. It'll only work if you enter the number manually per row.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<table class="table table-bordered" border="1" id="applicanttable">
<thead>
<tr>
</tr>
</thead>
<tbody>
<div class="row">
<tr>
<th>#</th>
<th>Number</th>
<th>Action</th>
</tr>
<tr id="row_0">
<td>
<input id="#" name="#" class="auto_num" type="text" value="1" readonly />
</td>
<td class="labelcell">
<input value="" class="form" name="lightBand1" placeholder="" id="lightBand1" />
<span class="email_result"></span>
</td>
<td class="labelcell">
<input type="button" class="removerow" id="removerow0" name="removerow0" value="Remove">
</td>
</tr>
</div>
</tbody>
<tfoot>
<tr>
</tr>
<tr>
<button type="button" id="addrow" style="margin-bottom: 1%;">Add Row</button>
</tr>
</tfoot>
</table>
You can call your event handler i.e : change whenever you change your input values by auto numbering . So , use $(this).trigger("change") where this refer to input where value is changed .
Demo Code :
$("#addrow").on('click', function() {
let rowIndex = $('.auto_num').length + 1;
let rowIndexx = $('.auto_num').length + 1;
var newRow = '<tr><td><input class="auto_num" type="text" name="entryCount" value="' + rowIndexx + '" /></td>"' +
'<td><input name="lightBand' + rowIndex + '" value="" class="form" type="number" /> <span class="email_result"></span></td>"' +
'<td><input type="button" class="removerow" id="removerow' + rowIndex + '" name="removerow' + rowIndex + '" value="Remove"/></td>';
$("#applicanttable > tbody > tr:last").after(newRow);
});
//this is for my validation
$(document).on('change', 'input[name*=lightBand]', function() {
var lightBand1 = $(this).val(); //get value
var selector = $(this) //save slector
selector.next('.email_result').html("") //empty previous error
if (lightBand1 != '') {
/*$.ajax({
url: "<?php echo base_url(); ?>participant/check_number_avalibility",
method: "POST",
data: {
lightBand1: lightBand1
},
success: function(data) {*/
selector.next('.email_result').html("NOT GOOD"); //use next here ..
/* }
});*/
}
});
// this is for autonumbering when ctrl+enter is pressed.
$(document).on('keyup', '.form', function(e) {
let value = parseInt(e.target.value);
if ((e.ctrlKey || e.metaKey) && (e.keyCode == 13 || e.keyCode == 10)) {
//loop through all values...
$(".form").each(function(i) {
if (i !== 0) {
$(this).val(++value); //assign new value..
$(this).trigger("change") //call your change event to handle further...
}
})
}
})
Add a row and type any number at number textbox column and press ctrl+enter. You'll see the "Not good" is not working on added rows. It'll only work if you enter the number manually per row.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<table class="table table-bordered" border="1" id="applicanttable">
<thead>
<tr>
</tr>
</thead>
<tbody>
<div class="row">
<tr>
<th>#</th>
<th>Number</th>
<th>Action</th>
</tr>
<tr id="row_0">
<td>
<input id="#" name="#" class="auto_num" type="text" value="1" readonly />
</td>
<td class="labelcell">
<input value="" class="form" name="lightBand1" placeholder="" id="lightBand1" />
<span class="email_result"></span>
</td>
<td class="labelcell">
<input type="button" class="removerow" id="removerow0" name="removerow0" value="Remove">
</td>
</tr>
</div>
</tbody>
<tfoot>
<tr>
</tr>
<tr>
<button type="button" id="addrow" style="margin-bottom: 1%;">Add Row</button>
</tr>
</tfoot>
</table>

Live search in table for specific column

I'm currently trying to create a live search for a specific column in a table. I've searched a bit but I can only find solutions to search over all columns. This is my code:
function searchInTable(table) {
var value = this.value.toLowerCase().trim();
jQuery(table).each(function (index) {
if (!index) return;
jQuery(this).find("td").each(function () {
var id = $(this).text().toLowerCase().trim();
var not_found = (id.indexOf(value) == -1);
$(this).closest('tr').toggle(!not_found);
return not_found;
});
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="search-table-input" class="search-table-input" type="text"
onkeyup="searchInTable('.table tr')" placeholder="Search Number...">
<table class="table">
<thead>
<tr>
<th class="table-number">
<span class="nobr">Number</span>
</th>
<th class="table-date">
<span class="nobr">Date</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a>264</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
<tr>
<td>
<a>967</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
<tr>
<td>
<a>385</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
<tr>
<td>
<a>642</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
</tbody>
</table>
My function has some errors and don't work like it should.
How can I change my function that way that when I start typing only the number gets filtered? I need to make the function dynamically so that I can pass the column which should be used for the search.
The line that's causing it to search over all the columns is this one:
jQuery(this).find("td").each(function () {
...which takes each cell in the current row and looks to see if it contains value. If you only want to check as specific column, you should pass in the column index as something like columnIndex, and then you can select the correct column by doing jQuery(this).find("td").eq(columnIndex), using jQuery's .eq() function to select the correct one. The code should look something like this:
function searchInTableColumn(table, columnIndex) {
//check this.value exists to avoid errors
var value = this.value ? this.value.toLowerCase().trim() : "";
jQuery(table).each(function (index) {
if (!index) return;
var tableCell = jQuery(this).find("td").eq(columnIndex);
var id = tableCell.text().toLowerCase().trim();
var not_found = (id.indexOf(value) == -1);
$(this).closest('tr').toggle(!not_found);
});
}
Then you can call searchInTableColumn(table, 0) and it will only look in the first column.

how to get dynamically generated table td input value

I have a dynamically generated table like below
this is the code that generate this table
function pullInventory(data) {
var container = document.getElementById('inventoryContainer')
var index = 0;
console.log(index)
data.forEach(function(awardsSnap) {
index ++;
// console.log(awardsSnap, index)
var awardItem = awardsSnap.val()
// Attach an asynchronous callback to rea
var NSNcard = `
<tr>
<td class="serial">${awardItem.NSN}</td>
<td> ${awardItem.Nomenclature} </td>
<td> ${awardItem.Awarddate} </td>
<td> ${awardItem.Awardid} </td>
<td>
<input type="text" placeholder="i.e. 100 EA" class="form-control" value="" id="qty${index}"style="width: 110px;">
</td>
<td>
<input type="text" placeholder="i.e. $9.23 " class="form-control" value="" style="width: 110px;">
</td>
</tr>
`;
container.innerHTML += NSNcard;
});
}
I want to get all the user entered quantity and price on a button click so I use this
document.querySelector("#savebtn").addEventListener("click", e => {
var rows = document.getElementById("WelcomeTable").getElementsByTagName("tbody")[0].getElementsByTagName("tr").length;
saveInventory(rows);
});
function saveInventory(rows) {
const columnHeader = Array.prototype.map.call(
document.querySelectorAll(".table th"),
th => {
return th.innerHTML;
}
);
const tableContent = Object.values(
document.querySelectorAll(".table tbody tr")
).map(tr => {
const tableRow = Object.values(tr.querySelectorAll("td")).reduce(
(accum, curr, i) => {
const obj = { ...accum };
obj[columnHeader[i]] = curr.innerHTML.trim();
console.log(accum, curr, i)
return obj;
},
{}
);
return tableRow;
});
}
everything works fine except that the two input column in the table above does not detect user input. I'm not able to get the quantity and price value entered.
Award Date: "08-23-2012"
Award#: "SP452013D0055"
NSN: "S222V00004789"
Nomenclature: " BATTERIES, NICKEL-CADMIUM"
Quantity: "<input type="text" placeholder="i.e. 100 EA" class="form-control" value="" id="qty18" style="width: 110px;">"
Unit-Price: "<input type="text" placeholder="i.e. $9.23 " class="form-control" value="" style="width: 110px;">"
I tried this and other things but they output undefine
obj[columnHeader[4]]=curr.val();
obj[columnHeader[4]]=curr.value;
how could i get the enetered quantity and price from the dynamic table?
You could try doing something like this:
window.onload = ()=>{
let targetTable = document.getElementById('target-table');
let targetTableRows = targetTable.rows;
let tableHeaders = targetTableRows[0];
// start from the second row as the first one only contains the table's headers
for(let i = 1; i < targetTableRows.length; i++){
// loop over the contents of each row
for(let j = 0; j < targetTableRows[i].cells.length; j++){
// something we could use to identify a given item
let currColumn = tableHeaders.cells[j].innerHTML;
// the current <td> element
let currData = targetTableRows[i].cells[j];
// the input field in the row
let currDataInput = currData.querySelector('input');
// is the current <td> element containing an input field? print its value.
// Otherwise, print whatever is insside
currDataInput ? console.log(`${currColumn}: ${currDataInput.value}`)
: console.log(`${currColumn}: ${currData.innerHTML}`);
}
}
};
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<table class="table" id="target-table">
<thead>
<tr>
<th scope="col">Person #</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
<th scope="col">Quantity</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
<td><input type="text" value="01-quantity" id="value-01"></td>
<td><input type="text" value="01-price" id="value-01-2"></td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
<td><input type="text" value="02-quantity" id="value-02"></td>
<td><input type="text" value="02-price" id="value-02-2"></td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>#twitter</td>
<td><input type="text" value="03-quantity" id="value-03"></td>
<td><input type="text" value="03-price" id="value-03-2"></td>
</tr>
</tbody>
</table>
What is done in the example above should also work for your specific case.
Also, here's a working exmaple :)
val() is jQuery method. You'll need to use .value in JavaScript.
obj[columnHeader[i]] = curr.innerHTML.trim();
innerHtml.trim returns only tag having direct child with text in it. In your code last two td having an input as child.
so in that case you need to check 'curr' having a child available. if there is a child available and its tagName is input, then you have to use childs value.
for example
obj[columnHeader[i]] = curr.children.length && curr.children[0].tagName=="INPUT" ? curr.children[0].value : curr.innerHTML.trim();
the above condition can be check and assign to a variable before it is assigned to key

Bootstrap/JQuery Table Filter is not working

I canĀ“t figure out why the filter is not working.
This is my input filed (which is the filter) an the table, both written in pug.
input#myInput.form-control(type='text', placeholder='Search..')
table.table.table-hover
thead
tr
th(scope='col') E-Mail
th(scope='col') Rolle
tbody#myTable
each user in users
tr
td #{user.local.email}
td #{user.local.role}
And here is the javascript document
$(document).ready(function(){
$("#myInput").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
Your are trying to filter table row <TR> and the content is inside <td> you need to check get by each <td> to find value
Try this :
$(document).ready(function(){
$("#myInput").on("keyup", function () {
var rows = $(".myTable").find("tr").hide();
if (this.value.length) {
var data = this.value.toLowerCase().split(" ");
$.each(data, function (i, v) {
rows.filter(":contains('" + v + "')").show();
});
} else rows.show();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="myInput" placeholder="Search here" />
<table class="myTable">
<tr>
<td>lion</td>
</tr>
<tr>
<td>cat</td>
</tr>
<tr>
<td>dog</td>
</tr>
<tr>
<td>mouse</td>
</tr>
</table>

Categories

Resources