How to use "class" instead of "ID" in jQuery .each() function? - javascript

I am trying to get value of subtotal field in my table, currently i am using table ID in .each function but my table ID increments dynamically on each section added, that is why i am not able to get value of subtotal and add each subtotal to get grand total.
This function is adding sub_totals to get grand subtotal
function calculateTableSum(currentTable) {
var sum = 0;
$('#' + currentTable + ' input.sub_total').each(function() {
//add only if the value is number
if(!isNaN(this.value) && this.value.length!=0) {
sum += parseFloat(this.value);
}
});
//.toFixed() method will roundoff the final sum to 2 decimal places
$('#' + currentTable + ' input.sumamtcollected').val(sum.toFixed(2));
This is where is want to use table class instead of table ID
$('#' + currentTable + ' input.sumamtcollected').each(function() {
//add only if the value is number
if(!isNaN(this.value) && this.value.length!=0) {
grand += parseFloat(this.value);
alert(this.value);
}
This is my table
<table id="addaccount'+counter+'" class="table table-bordered"><tbody> <tr class="invoice-total" bgcolor="#f1f1f1"><td colspan="3" align="right"><strong>Sub-Total</strong></td><td><i class="fa fa-inr"></i><input class="sumamtcollected form-control " name="accttotal[]" type="text" value="" readonly style="background-color:white" ></td><td></td></tr></body></table>
Where currentTable is
var currentTable = $(this).closest('table').attr('id');

Alternatively, you may modify your selector to query all table's that have an id that start with 'addaccount' like so:
$('table[id^="addaccount"]')
$('table[id^="addaccount"]').each(function() {
console.log(this);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="addaccount1" class="table table-bordered">
<tbody>
<tr class="invoice-total" bgcolor="#f1f1f1">
<td colspan="3" align="right"><strong>Sub-Total</strong></td>
<td><i class="fa fa-inr"></i><input class="sumamtcollected form-control " name="accttotal[]" type="text" value="" readonly style="background-color:white"></td>
<td></td>
</tr>
</body>
</table>
<table id="addaccount2" class="table table-bordered">
<tbody>
<tr class="invoice-total" bgcolor="#f1f1f1">
<td colspan="3" align="right"><strong>Sub-Total</strong></td>
<td><i class="fa fa-inr"></i><input class="sumamtcollected form-control " name="accttotal[]" type="text" value="" readonly style="background-color:white"></td>
<td></td>
</tr>
</body>
</table>

Related

Calculate the row date depending on previous row in the table

I have this dynamic table. Add more button append a new row. Row consists of number or days and date field. Means how many days added results in date.
Now in the second row, if I add a number of days; it must check the previous previous row date or number and result the date. But rowSelected.prev('tr')[0] gives me no value.
Can anybody please help me.
$(function() {
$("#add-more").click(function() {
$("#main-table").each(function() {
let tds = '<tr>';
jQuery.each($('tr:last td', this), function() {
tds += '<td>' + $(this).html() + '</td>';
});
tds += '</tr>';
if ($('tbody', this).length > 0) {
$('tbody', this).append(tds);
} else {
$(this).append(tds);
}
});
});
$(document).on('change', '.total-days', function(e) {
let rowSelected = $(this).closest('tr');
const someDate = new Date();
someDate.setDate(someDate.getDate() + parseInt($(this).val()));
const newDate = someDate.toISOString().substr(0, 10);
rowSelected.find('.expected-delivery-date').val(newDate);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="col-sm-6 right">
<a class="inline btn btn-primary" id="add-more">Add More</a>
</div>
<table class="table table-bordered" id="main-table" border="1">
<thead>
<tr>
<th>No.</th>
<th>From</td>
<th>Expected Delivery Date</td>
</tr>
</thead>
<tbody id="rows">
<tr>
<td><input class="form-control" type="text" name="deliverableNumber[]" /></td>
<td><input class="form-control total-days" type="number" value="1" name="deliverableNumberOfDays[]" /></td>
<td>
<input class="form-control expected-delivery-date" type="date" name="deliverableExpectedDeliveryDate[]" />
</td>
<td><i class="fa-2x fa fa-trash" onclick="SomeDeleteRowFunction(this)" title="Remove row"></i></td>
</tr>
</tbody>
</table>

Dynamically change text in table using by clicking a checkbox

I have a data in JSON format and I convert it to a HTML table. Now I want to
change the text from False to True if I check the checkbox. How can I do that?
Here is the code for creating the HTML table:
$.each(result, function (index, value) {
var Data = "<tr>" +
"<td class='' id='stdID' >" + value.StudentID + "</td>" +
"<td class='' id='stdRol'>" + value.RollNo + "</td>" +
"<td class='' id='stdName'>" + value.FirstName + "</td>" +
"<td class='cbx' value='1'><input type='checkbox' id='cc"+index+"'><span id='checkbox-value'> False</span></td>" +
"</tr>";
SetData.append(Data);
This is the result of this: output
To achieve what you require you need to use a delegated event handler, as you dynamically append the rows after the page has loaded, to hook to the change event of the checkboxes. Then you can set the text of the sibling span element based on the checked property. Something like this:
$('table').on('change', ':checkbox', function() {
$(this).next('span').text(this.checked);
});
span.checkbox-value { text-transform: capitalize; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td class="stdID">value.StudentID</td>
<td class="stdRol">value.RollNo</td>
<td class="stdName">value.FirstName</td>
<td class="cbx" value="1">
<input type="checkbox" id="cc1">
<span class="checkbox-value">False</span>
</td>
</tr>
<tr>
<td class="stdID">value.StudentID</td>
<td class="stdRol">value.RollNo</td>
<td class="stdName">value.FirstName</td>
<td class="cbx" value="1">
<input type="checkbox" id="cc2">
<span class="checkbox-value">False</span>
</td>
</tr>
</table>
You should note that your loop is creating multiple elements which have the same id, which is invalid HTML. In the example above I've changed them to classes instead.
Another way around to achieve your desired output
$(document).on('change', '.changeStatus', function() {
var row = $(this).closest('tr');
if($(this). prop("checked") == true){
row.find('.changeValue').html('True');
} else {
row.find('.changeValue').html('False');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>Id</td>
<td>Roll_no</td>
<td><input type="checkbox" class="changeStatus"></td>
<td class="changeValue">False</td>
</tr>
<tr>
<td>Id</td>
<td>Roll_no</td>
<td><input type="checkbox" class="changeStatus"></td>
<td class="changeValue">False</td>
</tr>
<tr>
<td>Id</td>
<td>Roll_no</td>
<td><input type="checkbox" class="changeStatus"></td>
<td class="changeValue">False</td>
</tr>
</tbody>
</table>

Why does it keep on duplicating the current row I’m updating?

So I’ve been encountering another problem from the last code I’ve posted: it keeps on duplicating the current row I’m updating. The code for updating the row is fine, it stays at the same position not below all the rows, but the only problem is that it duplicates the current row I’m updating. This is my last problem and my code is done. Hope y’all could help me.
function remove(deletelink) {
$(deletelink).closest("tr").remove();
if ($("tbody").find("tr").length == 0) {
$("tbody").append("<tr id='nomore'><td colspan='4'>No more records.</td></tr>");
}
return false;
}
function edit(editlink) {
var name = $(editlink).closest("tr").find("td.name").text();
var course = $(editlink).closest("tr").find("td.course").text();
$("#name").val(name);
$("#course").val(course);
$("#button").val("SAVE");
}
$(document).ready(function() {
let row = null;
//DELETE RECORD
$(".delete").click(function() {
remove(this);
});
//EDIT RECORD
$(".edit").click(function() {
row = $(this).closest('tr');
$('#name').val(row.find('td:eq(0)').text())
$('#course').val(row.find('td:eq(1)').text())
edit(this);
});
$("#button").click(function() {
var name = $("#name").val();
var course = $("#course").val();
//REMOVE "NO MRORE RECORDS WHEN ADDING"
if ($("tbody").find("tr#nomore").length > 0) {
$("tbody").html("");
}
//ADD RECORD
$("tbody").append("<tr><td class='name'>" + name + "</td><td class='course'>" + course + "</td><td><a href='#' class='edit'>Edit</a></td><td><a href='#' class='delete'>Delete</a></td></tr>");
//UPDATE RECORD
if (row) {
row.find('td:eq(0)').text($('#name').val());
row.find('td:eq(1)').text($('#course').val());
$('#name').val('');
$('#course').val('');
}
//DELETE THE NEWLY UPDATED RECORD
$(".delete").click(function() {});
$(".delete").click(function() {
remove(this);
});
//EDIT RECORD AFTER DELETING
$(".edit").click(function() {});
$(".edit").click(function() {
edit(this);
});
});
});
<!DOCTYPE html>
<html>
<head>
<title>Sample jQuery</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="name" placeholder="Name" />
<input type="text" id="course" placeholder="Course" />
<input type="button" id="button" value="ADD" />
<br /><br />
<table border="1" cellpadding="3">
<thead>
<tr>
<th>Name</th>
<th>Course</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">Joaquin</td>
<td class="course">BSIT</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
<tr>
<td class="name">Jump</td>
<td class="course">BSIT</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
<tr>
<td class="name">Ersan</td>
<td class="course">BSHRM</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
<tr>
<td class="name">Laree</td>
<td class="course">BSIT</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
</tbody>
</table>
</body>
</html>
You're using the same button for both add and update. When you are updating, it is calling the append part, which you don't want to do:
//ADD RECORD
$("tbody").append("<tr><td class='name'>" + name + "</td><td class='course'>" + course + "</td><td><a href='#' class='edit'>Edit</a></td><td><a href='#' class='delete'>Delete</a></td></tr>");
You need to check if you are adding or editing before this append.
If the record is going to be updated then no need to add it in table.
Modified code:
//UPDATE RECORD
if (row) {
row.find('td:eq(0)').text($('#name').val());
row.find('td:eq(1)').text($('#course').val());
$('#name').val('');
$('#course').val('');
}
else
{
//ADD RECORD
$("tbody").append("<tr><td class='name'>" + name + "</td><td class='course'>" + course + "</td><td><a href='#' class='edit'>Edit</a></td><td><a href='#' class='delete'>Delete</a></td></tr>");
}
Full code:
function remove(deletelink) {
$(deletelink).closest("tr").remove();
if ($("tbody").find("tr").length == 0) {
$("tbody").append("<tr id='nomore'><td colspan='4'>No more records.</td></tr>");
}
return false;
}
function edit(editlink) {
var name = $(editlink).closest("tr").find("td.name").text();
var course = $(editlink).closest("tr").find("td.course").text();
$("#name").val(name);
$("#course").val(course);
$("#button").val("SAVE");
}
$(document).ready(function() {
let row = null;
//DELETE RECORD
$(".delete").click(function() {
remove(this);
});
//EDIT RECORD
$(".edit").click(function() {
row = $(this).closest('tr');
$('#name').val(row.find('td:eq(0)').text())
$('#course').val(row.find('td:eq(1)').text())
edit(this);
});
$("#button").click(function() {
var name = $("#name").val();
var course = $("#course").val();
//REMOVE "NO MRORE RECORDS WHEN ADDING"
if ($("tbody").find("tr#nomore").length > 0) {
$("tbody").html("");
}
//UPDATE RECORD
if (row) {
row.find('td:eq(0)').text($('#name').val());
row.find('td:eq(1)').text($('#course').val());
$('#name').val('');
$('#course').val('');
}
else
{
//ADD RECORD
$("tbody").append("<tr><td class='name'>" + name + "</td><td class='course'>" + course + "</td><td><a href='#' class='edit'>Edit</a></td><td><a href='#' class='delete'>Delete</a></td></tr>");
}
//DELETE THE NEWLY UPDATED RECORD
$(".delete").click(function() {});
$(".delete").click(function() {
remove(this);
});
//EDIT RECORD AFTER DELETING
$(".edit").click(function() {});
$(".edit").click(function() {
edit(this);
});
});
});
<!DOCTYPE html>
<html>
<head>
<title>Sample jQuery</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="name" placeholder="Name" />
<input type="text" id="course" placeholder="Course" />
<input type="button" id="button" value="ADD" />
<br /><br />
<table border="1" cellpadding="3">
<thead>
<tr>
<th>Name</th>
<th>Course</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">Joaquin</td>
<td class="course">BSIT</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
<tr>
<td class="name">Jump</td>
<td class="course">BSIT</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
<tr>
<td class="name">Ersan</td>
<td class="course">BSHRM</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
<tr>
<td class="name">Laree</td>
<td class="course">BSIT</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
</tbody>
</table>
</body>
</html>
You are getting the duplication because your save action has an append in it
//ADD RECORD
$("tbody").append("<tr><td class='name'>" + name + "</td><td class='course'>" + course + "</td><td><a href='#' class='edit'>Edit</a></td><td><a href='#' class='delete'>Delete</a></td></tr>");
Use the row variable you are setting as an if condition to see if you should add or edit
if(!row){
$("tbody").append("<tr><td class='name'>" + name + "</td><td class='course'>" + course + "</td><td><a href='#' class='edit'>Edit</a></td><td><a href='#' class='delete'>Delete</a></td></tr>");
} else {
row.find('td:eq(0)').text($('#name').val());
row.find('td:eq(1)').text($('#course').val());
$('#name').val('');
$('#course').val('');
//set row back to null
row=null;
}
You are also creating new click handlers for all your rows each time "Save" is clicked, not just adding a new one to a new row. This will cause duplicated event calls for a single click. Use event delegation and you will only need to setup click handlers once:
$("table").on('click','.delete',function() {
remove(this);
});
//EDIT RECORD
$("table").on('click','.edit',function() {
row = $(this).closest('tr');
$('#name').val(row.find('td:eq(0)').text())
$('#course').val(row.find('td:eq(1)').text())
edit(this);
});

Trying to sum from a jquery selector and update an element

I need to sum some text elements and update an input text, following is the far I could go:
This would be a correct example. I want to sum the text from within the <span> if the the <tr> contains the class ui-state-error
HTML
<table>
<tr id="rp-10-1-1" class="ui-state-error" style="width:50px; height:50px;">
<td><span id="pr-10-1-1">100</span><td>
</tr>
<tr id="rp-10-1-2" class="ui-state-highlight" style="width:50px; height:50px;">
<td><span id="pr-10-1-2">200</span><td>
</tr>
<tr id="rp-10-1-3" class="ui-state-error" style="width:50px; height:50px;">
<td><span id="pr-10-1-3">300</span><td>
</tr>
</tr>
</table>
<input type="text" id="sumhere">
JAVASCRIPT
$( 'tr[id^="rp-"]' ).click(
function() {
$('tr[id^="rp-"]').each(function(data, val) {
var rps = $(this).attr("id").split("-");
if ($("#pr-" + rps[1] + '-' + rps[2] + '-' + rps[3]).hasClass("ui-state-error")) {
console.log($("#pr-" + rps[1] + "-" + rps[2] + "-" + rps[3]).text());
}
});
}
);
tr would td are not recognized as a valid html. If you wish to extract just the total of the span elements, you may do the following :
var total = 0;
$('span[id^=hp]').each(function() // selects span starting with id=hp
{
total += parseInt($(this).text());
});
$("#sumhere").val(total);
Based on your updated HTML :
var total = 0;
$('tr[id^=rp-10-1] span').each(function() // selects span withing the tr element starting with id=rp-10-1
{
if(!isNaN(parseInt($(this).text()))) // condition for safety check while converting text to interger.
total += parseInt($(this).text());
});
$("#sumhere").val(total);
Example : https://jsfiddle.net/DinoMyte/7nhx26a2/3/
Demo: https://jsfiddle.net/zzaj1jye/
HTML:
<tr id="rp-10-1-1">
<span id="hp-10-1-1" class="ui-state-error">10</span>
<span id="hp-10-1-2" class="ui-state-error">20</span>
<span id="hp-10-1-3" class="ui-state-error">30</span>
</tr>
<input type="text" id="sumhere">
JS:
$(function() {
var total = 0;
$('span').each(function() {
if ( $(this).hasClass('ui-state-error') ) {
total += parseInt($(this).text());
}
});
$("#sumhere").val(total);
});

jquery to sum two inputs on dynamic table and display in third

With the SO community I have got a script that adds rows with unique names to a table. I want to take two inputs on each row and multiply them together and display result in a third input.
the fiddle is at http://jsfiddle.net/yUfhL/231/
My code is:
HTML
<table class="order-list">
<tr><td>Product</td><td>Price</td><td>Qty</td><td>Total</td></tr>
<tr>
<td><input type="text" name="product" /></td>
<td><input type="text" name="price" /></td>
<td><input type="text" name="qty" /></td>
<td><input type="text" name="linetotal" /></td>
</tr>
</table>
<div id="grandtotal">
Grand Total Here
</div>
JS
var counter = 1;
jQuery("table.order-list").on('change','input[name^="product"]',function(event){
event.preventDefault();
counter++;
var newRow = jQuery('<tr><td><input type="text" name="product' +
counter + '"/></td><td><input type="text" name="price' +
counter + '"/></td><td><input type="text" name="qty' +
counter + '"/></td><td><input type="text" name="total' +
counter + '"/></td><td><a class="deleteRow"> x </a></td></tr>');
jQuery('table.order-list').append(newRow);
});
jQuery("table.order-list").on('click','.deleteRow',function(event){
$(this).closest('tr').remove();
});
$('table.order-list tr').each(function() {
var price = parseInt( $('input[id^=price]', this).val(), 10 );
var qty = parseInt( $('input[id^=qty]' , this).val(), 10 );
$('input[id^=linetotal]', this).val(price * qty);
});
So currently I cant get the js to fire that gets the product of the two cells, qty and price. I want to display result in linetotal.
The last part of this would be to display the sum of all linetotals as a grand total in the div grandtotal
Help appreciated as always.
You're only giving the elements a name attribute, but using the id selector ([id^=price]). It's much easier to give them a specific class than having to use that "id starts with" selector. Also, when do you want the line totals to be calculated? And when do you want the grand total to be calculated? On what event(s)?
Here's my interpretation of how it should look:
<table class="order-list">
<thead>
<tr><td>Product</td><td>Price</td><td>Qty</td><td>Total</td></tr>
</thead>
<tbody>
<tr>
<td><input type="text" name="product" /></td>
<td>$<input type="text" name="price" /></td>
<td><input type="text" name="qty" /></td>
<td>$<input type="text" name="linetotal" readonly="readonly" /></td>
<td><a class="deleteRow"> x </a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: center;">
<input type="button" id="addrow" value="Add Product" />
</td>
</tr>
<tr>
<td colspan="5">
Grand Total: $<span id="grandtotal"></span>
</td>
</tr>
</tfoot>
</table>
And the JS:
$(document).ready(function () {
var counter = 1;
$("#addrow").on("click", function () {
counter++;
var newRow = $("<tr>");
var cols = "";
cols += '<td><input type="text" name="product' + counter + '"/></td>';
cols += '<td>$<input type="text" name="price' + counter + '"/></td>';
cols += '<td><input type="text" name="qty' + counter + '"/></td>';
cols += '<td>$<input type="text" name="linetotal' + counter + '" readonly="readonly"/></td>';
cols += '<td><a class="deleteRow"> x </a></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
});
$("table.order-list").on("change", 'input[name^="price"], input[name^="qty"]', function (event) {
calculateRow($(this).closest("tr"));
calculateGrandTotal();
});
$("table.order-list").on("click", "a.deleteRow", function (event) {
$(this).closest("tr").remove();
calculateGrandTotal();
});
});
function calculateRow(row) {
var price = +row.find('input[name^="price"]').val();
var qty = +row.find('input[name^="qty"]').val();
row.find('input[name^="linetotal"]').val((price * qty).toFixed(2));
}
function calculateGrandTotal() {
var grandTotal = 0;
$("table.order-list").find('input[name^="linetotal"]').each(function () {
grandTotal += +$(this).val();
});
$("#grandtotal").text(grandTotal.toFixed(2));
}
http://jsfiddle.net/QAa35/
In your JS, you weren't using linetotal for the one dynamic input's name. There were other several minor modifications I made. You might as well use <thead>, <tbody> and <tfoot> since you do have those sections in the <table>. Also, I don't think it's a good design to have a new row automatically added when the "product" inputs are changed. That can happen often, and their intent may not be to add a new product...a button is much more friendly. For example, say you type in "asdf" to the first "product" input, then click somewhere. A new row is added. Say you made a typo so you go back and change it to "asd", then click somewhere. Another new row is added. That doesn't seem right.
This function should do the trick:
function updateGrandTotal() {
var prices = [];
$('input[name^="price"]').each(function () {
prices.push($(this).val());
});
var qnts = [];
$('input[name^="qty"]').each(function () {
qnts.push($(this).val());
});
var total = 0;
for(var i = 0; i < prices.length; i++){
total += prices[i] * qnts[i];
}
$('#grandtotal').text(total.toFixed(2));
}
You just need to bind it to the table change event to update the grand total every time an input changes:
$("table.order-list").change(updateGrandTotal);
Here is a working fiddle.

Categories