admin管理员组文章数量:1356914
I'm trying to sum the values of one specific column but honestly I dont know how to it, also I want to refresh that total value when I add or remove some row, what can I do to make this? I'm triying with the anwsers of similar question here on SO but they sum values from all columns and I only want to do that for an specific column! Here is what I have:
function deleteRow(btn) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
}
$('#xd').click(function() {
var lines = "";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td>1</td>';
lines += '<td>100.00</td>';
lines += '<td><input type="button" value="Delete" onclick="deleteRow(this)"/></td>';
$('#TableBody').append(lines);
})
<script src=".1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td>10</td>
<td>12.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td>5</td>
<td>10.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td>15</td>
<td>170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
I'm trying to sum the values of one specific column but honestly I dont know how to it, also I want to refresh that total value when I add or remove some row, what can I do to make this? I'm triying with the anwsers of similar question here on SO but they sum values from all columns and I only want to do that for an specific column! Here is what I have:
function deleteRow(btn) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
}
$('#xd').click(function() {
var lines = "";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td>1</td>';
lines += '<td>100.00</td>';
lines += '<td><input type="button" value="Delete" onclick="deleteRow(this)"/></td>';
$('#TableBody').append(lines);
})
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td>10</td>
<td>12.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td>5</td>
<td>10.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td>15</td>
<td>170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
In the above code I added the Total columns (Price, Quantity) manually, I want to update total result when user add/remove a row.
Share Improve this question asked Jan 15, 2017 at 0:30 User1899289003User1899289003 8722 gold badges24 silver badges47 bronze badges5 Answers
Reset to default 2Your approach is a bit brittle for long term use, but as a proof of concept this may help.
The key technique for summing up an array of numbers is to use Array.reduce
, which works like this:
var array = [1, 2, 6, 1, 5];
var total = array.reduce(function(total, number) {
return total + number;
}, 0);
document.write('<h1>Total: <code>' + total + '</code></h1>');
Given an array of numbers, iterate over each of them and add number
to total
, with total
starting at 0
.
Array.reduce
takes two arguments: a function to execute over each item, and a starting value. The iterator function will receive two arguments, in your case the running total and the next number.
See the MDN documentation on Array.reduce
for more details.
Some Tips
- Break things down into smaller functions whenever possible.
- Limit use of global variables, but when you do need them, be clean and consistent about it
- Limit storing data on the DOM (I'm violating this slightly, but this is just sketch code)
- Try and write code in a way that's reusable
The benefits of this approach are it makes it a bit easier to add new features/change what you built. For example, if we write a generic function getColumnTotal(selector)
, which would let you specify a jQuery selector for a column's cells (ex: .priceCell
), then you can reuse that for other columns like quantity
.
I assume you were working towards a grand total cell, that displays the total of all individual orders/rows. To do that, all we'd need to do is calculate the subtotal
for each row, add a new column for that, then re-use that getColumnTotal
function to sum up all the sub-totals. Voila, grand total.
Note that my code doesn't account for errors, so you may need to handle situations where invalid quantity
or price
data is input.
var $tableBody = $('#TableBody');
var $totalQuantityCell = $('#totalQuantityCell');
var $totalPriceCell = $('#totalPriceCell');
var $totalGrandCell = $('#grandTotalCell');
// Add a row with random values on "Add Row" button click
$('#xd').click(addRandomRow);
function addRandomRow(event) {
var randomCode = Math.round(Math.random() * 4);
var randomClient = Math.round(Math.random() * 15);
var randomCharge = ( Math.round(Math.random()) ? 'Debit' : 'Credit' );
var randomQuantity = Math.ceil(Math.random() * 5);
var randomPrice = Math.ceil(Math.random() * 100).toFixed(2);
addRow(randomCode, randomClient, randomCharge, randomQuantity, randomPrice);
};
// Add some rows to start
addRandomRow();
addRandomRow();
// Listen for clicks on ".deleteRowButton" within the table
$tableBody.on('click', '.deleteRowButton', function(event) {
deleteRow( $(event.target).data('row') );
updateTotals();
});
// --------------------------
function addRow(code, client, chargeType, quantity, price) {
// Create a new row element
var idNum = ( $tableBody.find('tr').length + 1 );
var rowId = 'row-' + idNum;
var $row = $('<tr id="' + rowId + '"></tr>');
// Add the table cells
$row.append('<td class="idCell">' + idNum + '</td>');
$row.append('<td class="codeCell">' + code + '</td>');
$row.append('<td class="clientCell">' + client + '</td>');
$row.append('<td class="chargeTypeCell">' + chargeType + '</td>');
$row.append('<td class="quantityCell">' + quantity + '</td>');
$row.append('<td class="priceCell">' + price + '</td>');
$row.append('<td class="orderTotalCell">' + getSubtotal(quantity, price) + '</td>');
$row.append('<td><input type="button" value="Delete" class="deleteRowButton" data-row="#' + rowId + '" /></td>');
// Append the row to the table body
$tableBody.append($row);
updateTotals();
}
function deleteRow(rowId) {
$(rowId).remove();
}
function updateTotals() {
var totalQuantity = getColumnTotal('.quantityCell');
var totalPrice = getColumnTotal('.priceCell');
var totalOrder = getColumnTotal('.orderTotalCell');
$totalQuantityCell.text( totalQuantity );
$totalPriceCell.text( toMoney(totalPrice) );
$totalGrandCell.text( toMoney(totalOrder) );
}
/**
A standard function to calaculate the subtotal of a row, this is
where you could apply tax or other data transformations if need be.
*/
function getSubtotal(quantity, price) {
return (quantity * price).toFixed(2);
}
/**
Takes a jQuery selector, finds all matching elements for it, and totals up their contents.
It works by converting the elements list to an Array and then using Array.reduce.
@see https://developer.mozilla/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
*/
function getColumnTotal(selector) {
return Array.from( $(selector) ).reduce(sumReducer, 0);
}
/**
The reducer function that adds up a running total. This function parses the innerHTML content
of an element and converts it to a number so math works on it.
*/
function sumReducer(total, cell) {
return total += parseInt(cell.innerHTML, 10);
}
function toMoney(number) {
return '$' + number.toFixed(2);
}
#TableHead td {
border-bottom: 1px #000 solid;
}
.orderTotalCell,
#grandTotalCell,
#totalPriceCell {
text-align: right;
}
#TableFooter tr:first-child td {
border-top: 1px #000 solid;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead id="TableHead">
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Order Total</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Sub-Total</td>
<td id="totalQuantityCell">–</td>
<td id="totalPriceCell">–</td>
<td id="grandTotalCell">–</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
wow lots of answers but here is a somewhat of a more object oriented approach.
function row(Id, Code, Client, DebitCredit, Quantity, Price) {
this.Id = Id;
this.Code = Code;
this.Client = Client;
this.DebitCredit = DebitCredit;
this.Quantity = Quantity;
this.Price = Price;
}
function model() {
this.rows = [];
}
var mymodel = new model();
$(document).ready(function() {
mymodel.rows.push(new row(1, 1, 3, 'Debit', 10, 12))
mymodel.rows.push(new row(2, 2, 12, 'Debit', 5, 10))
draw();
$("body").on("click", ".delete", function() {
var id = $(this).data('id');
for (i = 0; i < mymodel.rows.length; i++) {
console.log(mymodel.rows[i].Id);
if (mymodel.rows[i].Id == id) {
mymodel.rows.splice(i, 1);
}
}
draw();
});
$('#add').click(function() {
mymodel.rows.push(new row(
$('#Id').val(),
$('#Code').val(),
$('#Client').val(),
'Debit',
Number($('#Quantity').val()),
Number($('#Price').val())
))
draw();
});
})
function draw() {
$('tbody').empty();
var totalQuantity = 0;
var totalPrice = 0;
$.each(mymodel.rows, function(i, row) {
totalQuantity += row.Quantity;
totalPrice += row.Price;
var myrow = '<tr>'
$.each(row, function(key, value) {
myrow += '<td>' + value + '</td>'
});
myrow += '<td><input type="button" class="btn btn-danger delete" data-id="' + row.Id + '" value="X"/></td>'
myrow += '<tr>'
$('tbody').append(myrow);
});
$('#totalQuantity').text(totalQuantity)
$('#totalPrice').text(totalPrice)
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Latest piled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<table class="table table-condensed">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Delete</td>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan=7>Total Quantity:
<span id="totalQuantity"></span> Total Price:
<span id="totalPrice"></span>
</td>
</tr>
</tfoot>
</table>
<form class="form-inline">
<div class="form-group">
<label for="id">Id:</label>
<input type="number" class="form-control" id="Id">
</div>
<div class="form-group">
<label for="Code">Code:</label>
<input type="number" class="form-control" id="Code">
</div>
<div class="form-group">
<label for="Client">Client:</label>
<input type="number" class="form-control" id="Client">
</div>
<div class="form-group">
<label for="Quantity">Quantity:</label>
<input type="number" class="form-control" id="Quantity">
</div>
<div class="form-group">
<label for="Price">Price:</label>
<input type="number" class="form-control" id="Price">
</div>
<input type="button" class="btn btn-info" value="add" id="add" />
</form>
You are missing:
<tr> </tr>
Tags when you add a new row. Also, just add a class that will add up "Quantities" and "Prices". Here's a working solution. Hope it helps!
function deleteRow(btn) {
var row = btn.parentNode.parentNode;
row.parentNode.removeChild(row);
sumOfColumns();
}
function sumOfColumns(){
var totalQuantity = 0;
var totalPrice = 0;
$(".someClass").each(function(){
totalQuantity += parseInt($(this).html());
$(".someTotalClass").html(totalQuantity);
});
$(".classPrice").each(function(){
totalPrice += parseInt($(this).html());
$(".someTotalPrice").html(totalPrice);
});
}
$(document).ready(function () {
$('#xd').click(function() {
var lines = "";
lines += '<tr>';
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td class = "someClass">1</td>';
lines += '<td class = "classPrice">100.00</td>';
lines += '<td><input type="button" value="Delete" onclick="deleteRow(this)"/></td>';
lines += '</tr>';
$('#TableBody').append(lines);
sumOfColumns();
});
});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td class = "someClass">10</td>
<td class = "classPrice">12.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td class = "someClass">5</td>
<td class = "classPrice">10.00</td>
<td>
<input type="button" value="Delete" onclick="deleteRow(this)" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class = "someTotalClass">15</td>
<td class = "someTotalPrice"">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
You can create a function to calculate total and call it after you add each line and on page load if you have some initial value.
function setTotal()
{
var totalPrice=0;
var totalQty=0;
$('#TableBody').find('tr').each(
function(){
totalQty +=parseFloat($(this).find('td').eq(4).text());
totalPrice +=parseFloat($(this).find('td').eq(5).text());
//console.log(totalPrice);
});
$('#TableFooter').find('tr td').eq(1).text(totalQty);
$('#TableFooter').find('tr td').eq(2).text(totalPrice);
}
$(function(){
setTotal();
})
$('#ID').find('tr') will find all the rows of table with id 'ID'. then you iterate through each tr using each function. Then in each row you find all the td similarly and get to specific td using eq function. eq takes index of the element.
Here is running fiddler : https://jsfiddle/8a4umvdr/
There are several flaws within your script, which I will want to walk you through so that you can better understand the process:
Avoid using inline JS. If you want to bind events dynamically, you can use
.on()
instead. Since the table is present on DOM ready, you can use$('#Table').on(...)
to listen to click events on the delete buttonModularise sum putation into a single function. You can create a function, say
puteSum()
, which will be called every time you modify the table: be it when a table row is added, or a table row is deleted. You can also call this function at runtime, so that you do not have to use server-side languages to prepute the starting sums.- In my example below, I will fetch the text node in the 5th and 6th columns (which is
4
and5
by zero-based index), and convert them to float by appending+
in front of them - I have also used the
.toFixed(2)
function when printing the sums, so that its nicely showing two decimal places.
- In my example below, I will fetch the text node in the 5th and 6th columns (which is
Fix your HTML injection. Remember that for
<td>
elements to be valid, they have to be nested in<tr>
. You seem to have left that out by accident.
So here is a pletely functional example of your code snippet:
$(function() {
// Function to pute sum
var puteSum = function() {
// Get the total quantity and price by column index
var quantity = 0,
price = 0;
// Iterate through each row
$('#TableBody tr').each(function() {
quantity += +$(this).find('td').eq(4).text();
price += (+$(this).find('td').eq(5).text() * +$(this).find('td').eq(4).text());
});
// Update sum
$('#TableFooter td.total.quantity').text(quantity.toFixed(2));
$('#TableFooter td.total.price').text(price.toFixed(2));
};
// Use on to bind click event handlers to input buttons with delete-row action
$('#Table').on('click', 'input[type="button"][data-action="delete-row"]', function(e) {
e.preventDefault();
// Delete row
$(this).closest('tr').remove();
// Repute sum
puteSum();
});
$('#xd').click(function() {
// Remember to wrap your cells within <tr>
var lines = "<tr>";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td>1</td>';
lines += '<td>100.00</td>';
lines += '<td><input type="button" value="Delete" data-action="delete-row" /></td>';
lines += "</tr>";
// Append new table row
$('#TableBody').append(lines);
// Repute sum
puteSum();
});
// Compute sum when starting up
puteSum();
});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td>10</td>
<td>12.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td>5</td>
<td>10.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class="total quantity">15</td>
<td class="total price">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
Further improvements
There are some minor improvements that you can make to my code above, but they are considered non-mission critical and hence I did not include them in my original answer.
Extensibility. If you want to pute additional columns, it would be difficult to rewrite the same lines over and over again. Instead, I remend you store the sums in an object instead.
Value fetching. We are retrieving values based on the text node in the column. Sometimes, you do not want that—say you want to include currencies, or other texts in the quantity and/or price column. In that sense, you might want to store such data in a custom HTML5
data-
attribute instead.
$(function() {
// Function to pute sum
var puteSum = function() {
// Get the total quantity and price by column index
var sums = { quantity: 0, price: 0 };
// Iterate through each table cell
$('#TableBody tr').each(function() {
sums.quantity += +$(this).find('td').eq(4).data('value');
sums.price += (+$(this).find('td').eq(4).data('value')*+$(this).find('td').eq(5).data('value'));
});
// Update sum
$.each(sums, function(key, value) {
$('#TableFooter td.total.'+key).text(value.toFixed(2));
});
};
// Use on to bind click event handlers to input buttons with delete-row action
$('#Table').on('click', 'input[type="button"][data-action="delete-row"]', function(e) {
e.preventDefault();
// Delete row
$(this).closest('tr').remove();
// Repute sum
puteSum();
});
$('#xd').click(function() {
// Remember to wrap your cells within <tr>
var lines = "<tr>";
lines += '<td>3</td>';
lines += '<td>3</td>';
lines += '<td>15</td>';
lines += '<td>Credit</td>';
lines += '<td class="quantity" data-value="1">1</td>';
lines += '<td class="price" data-value="100.00">100.00</td>';
lines += '<td><input type="button" value="Delete" data-action="delete-row" /></td>';
lines += "</tr>";
// Append new table row
$('#TableBody').append(lines);
// Repute sum
puteSum();
});
// Compute sum when starting up
puteSum();
});
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="Table">
<thead>
<tr>
<td>ID</td>
<td>Code</td>
<td>Client</td>
<td>Debit/Credit</td>
<td>Quantity</td>
<td>Price</td>
<td>Options</td>
</tr>
</thead>
<tbody id="TableBody">
<tr>
<td>1</td>
<td>1</td>
<td>3</td>
<td>Debit</td>
<td class="quantity" data-value="10">10</td>
<td class="price" data-value="12.00">12.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>12</td>
<td>Debit</td>
<td class="quantity" data-value="5">5</td>
<td class="price" data-value="10.00">10.00</td>
<td>
<input type="button" value="Delete" data-action="delete-row" />
</td>
</tr>
</tbody>
<tfoot id="TableFooter">
<tr>
<td colspan="4">Total</td>
<td class="total quantity">15</td>
<td class="total price">170.00</td>
</tr>
</tfoot>
</table>
<input type="button" id="xd" value="add row">
本文标签: javascriptHow to sum values from table column and update when removeadd new rowStack Overflow
版权声明:本文标题:javascript - How to sum values from table column and update when removeadd new row - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744063717a2584599.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论