I'm working a project, it is almost done but I got a problem to finish it. I tried a lot of things and searched on the web, but unfortunately I could not succeed it.
The problem is about dynamically added rows at the table. Auto-calculating script is just working on the first row of the table, at 2nd, 3rd, ... rows of the table it does not work.
jsFiddle for below the code:
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$("#AddLine").click(function () {
//var row = "<tr><td><input type=text /></td><td><input type=text /></td><td><input type=text /></td><td><button>X</button></td></tr>";
var row = "<tr><td><input type=\"text\" style=\"width:100%;\" name=\"stokkodu[]\"></td><td><input type=\"text\" style=\"width:100%;\" name=\"stokadi[]\"></td><td><input type=\"text\" style=\"width:100%;\" id=\"miktar\" class=\"miktar\" name=\"miktar[]\"></td><td><input type=\"text\" style=\"width:100%;\" name=\"birim[]\"></td><td><input type=\"text\" style=\"width:100%;\" id=\"birimfiyat\" class=\"birimfiyat\" name=\"birimfiyat[]\"></td><td><input type=\"text\" style=\"width:100%;\" readonly id=\"tutar\" class=\"tutar\" name=\"tutar[]\"></td><td><input type=\"text\" style=\"width:100%;\" class=\"indirim\" name=\"indirim[]\"></td><td><input type=\"text\" style=\"width:100%;\" readonly class=\"indirimtutar\" name=\"indirimtutari[]\"></td><td><input type=\"text\" style=\"width:100%;\" class=\"kdv\" name=\"kdv[]\"></td><td><input type=\"text\" style=\"width:100%;\" readonly class=\"satirtoplami\" name=\"satirtoplami[]\"></td><td><button>X</button></td></tr>";
$("#table").append(row);
});
$("#table").on("click", "button", function() {
$(this).closest("tr").remove();
});
});
$(document).ready(function() {
$('input[id=miktar],input[id=birimfiyat],input[id=indirim],input[id=kdv], input[id=satirtoplami]').change(function(e) {
var total_mnozi = 0;
//var $row = $(this).parent();
var $row = $(this).closest("tr"); //this is the closest common root of the input elements
var miktar = parseFloat( $row.find('input[id=miktar]').val() );
var birimfiyat = parseFloat( $row.find('input[id=birimfiyat]').val() );
var indirim = parseFloat( $row.find('input[id=indirim]').val() );
var kdv = parseFloat( $row.find('input[id=kdv]').val() );
//total_mnozi = ((dep + minpre + adjpre) * procombase * profcomper) || 0; //calculate traditionally; display zero until result is meaningful
tutar = (miktar * birimfiyat) || 0; // tutar hesaplama. miktar x birim fiyat = tutar
indirimtutar= (tutar * indirim / 100) || 0; // indirim tutarı hesaplama input'a girilen %'ye göre hesaplar.
satirtoplami= ((tutar - indirimtutar) * ((kdv / 100) + 1 )) || 0;
$row.find('input[id=tutar]').val(tutar.toFixed(2)); // tutar'ın id="tutar"'a virgülden sonra 2 hane alacak şekilde yazdrılması.
$row.find('input[id=indirimtutar]').val(indirimtutar.toFixed(2));
$row.find('input[id=satirtoplami]').val(satirtoplami.toFixed(2));
});
});
//]]>
</script>
<input type="button" id="AddLine" value="add"/>
<table id="table">
<tr>
</tr>
<tr>
<td scope="col">Stok Kodu</th>
<td scope="col">Stok Adı</th>
<td scope="col">Miktar</th>
<td scope="col">Birim</th>
<td scope="col">Birim Fiyat</th>
<td scope="col">Tutar</th>
<td scope="col">İndirim (%)</th>
<td scope="col">İndirim Tutarı</th>
<td scope="col">KDV (%)</th>
<td scope="col">Satır Toplamı</th>
<td scope="col"></th>
</tr>
<tr>
<td><input type="text" style="width:100%;" name="stokkodu[]"></td>
<td><input type="text" style="width:100%;" name="stokadi[]"></td>
<td><input type="text" style="width:100%;" id="miktar" class="miktar" name="miktar[]"></td>
<td><input type="text" style="width:100%;" name="birim[]"></td>
<td><input type="text" style="width:100%;" id="birimfiyat" class="birimfiyat" name="birimfiyat[]"></td>
<td><input type="text" style="width:100%;" readonly id="tutar" class="tutar" name="tutar[]"></td>
<td><input type="text" style="width:100%;" id="indirim" class="indirim" name="indirim[]"></td>
<td><input type="text" style="width:100%;" readonly id="indirimtutar" class="indirimtutar" name="indirimtutari[]"></td>
<td><input type="text" style="width:100%;" id="kdv" class="kdv" name="kdv[]"></td>
<td><input type="text" style="width:100%;" readonly id="satirtoplami" class="satirtoplami" name="satirtoplami[]"></td>
<td><button>X</button></td>
</tr>
</table>
How can I do this?
Your problem is with duplicate Ids.
You should not add two or more elements with the same Id. So, to solve the problem, your dynamically added elements should not have id attributes, then you use the class attribute to target the elements in each row.
Working sample: http://jsfiddle.net/3W48W/2/ (incorporating #Barmar 's answer)
HTM
There are two problems with your code:
First, you're using the same IDs in each row that you add dynamically. IDs are required to be unique.
Second, the .change() binding only applies to elements that are in the DOM at the time the page is loaded. To handle elements added dynamically, you need to use .on() to bind to a permanent element and delegate to the dynamic elements, or bind the event handler to the new row's elements after you append it to the DOM.
Related
I am new into JQuery, My code is only working for the first row, it doesn't calculate for other rows. I have two button, one for adding another row and one for deleting it. What I try to do it to calculate price+vat*quantity and put it in total field in every row.
here if the code for my html
<table border='1' id="mytable" dir="rtl" style='border-collapse: collapse;'>
<thead>
<tr>
<th> partnumber </th>
<th>name</th>
<th>price </th>
<th>vat</th>
<th>quantity</th>
<th> price + vat</th>
<th> total quantity*(price+vat) </th>
<th> </th>
</tr>
</thead>
<tbody>
<tr class='tr_input'>
<td><input type='text' name="partnumber[]" class='username' id='partnumber_1' placeholder='پارت نهمبهر '></td>
<td><input type='text' class='name' name="name[]" id='name_1' ></td>
<td><input type='text' class='price' name="price[]" id='price_1' ></td>
<td><input type='text' class='vat' name="vat[]" id='vat_1' ></td>
<td><input type='text' class='quantity' name="quantity[]" id='quantity_1' ></td>
<td><input type='text' class='amount' name="amount[]" id='amount_1' ></td>
<td><input type='text' class='total' name="total[]" id='total_1' ></td>
</tr>
</tbody>
</table>
<br>
<input type='button' value='Add fields' id='addmore' class="btn btn-success">
<input type='button' value='remove' id='remove' class="btn btn-danger">
Here is the screenshot for the interface.
And this is JS code for adding new row
$('#addmore').click(function(){
var lastname_id = $('.tr_input input[type=text]:nth-child(1)').last().attr('id');
var split_id = lastname_id.split('_');
var index = Number(split_id[1]) + 1;
var html = "<tr class='tr_input'><td><input type='text' name='partnumber[]' class='username' id='username_"+index+"' placeholder='بگهری بۆ پارت نهمبهر '></td><td><input type='text' class='name' name='name[]' id='name_"+index+"'></td><td><input type='text' class='price' name='price[]' id='price_"+index+"' ></td><td><input type='text' class='vat' name='vat[]' id='vat"+index+"'></td><td><input type='text' class='quantity' name='quantity[]' id='quantity_"+index+"' ></td><td><input type='text' class='amount' name='amount[]' id='amount_"+index+"' ></td><td><input type='text' class='total' name='total[]' id='total_"+index+"' ></td><td align='center'><input type='checkbox' name='record'></td></tr>";
// Append data
$('tbody').append(html);
});
and finally this is code for calculation the total, only working for the first row.
$('.total').each(function() {
$(this).on('click',function (ev) {
// var total=0;
var quantity=$(this).attr('id');
var splitid = quantity.split('_');
var index = splitid[1];
var price= parseFloat($('#price_'+index).val());
var vat=parseFloat($('#vat_'+index).val());
var quan=parseFloat($('#quantity_'+index).val());
var amount=$('#amount_'+index).val();
amount=price+vat;
$('#amount_'+index).val(amount);
alert(amount);
//alert(price);
var total=amount*quan;
//var qunatity_num=parseInt(quantity.val());
$('#total_'+index).val(total);
//alert(total);
// $('#total_'+index).val(total);
});
});
please, could you tell me what's is wrong with my code, it's been a week I am trying to solve this. Thank you.
Some issues:
There is an underscore missing in the HTML that you add for a new row: vat should be vat_
Don't use $('.total').each(function() {: it is not necessary to loop. The click handler will work on all matching elements, if you take the next point into account:
Use event delegation to make sure your click handler also gets called for future cells that have the total class:
$(document).on('click', '.total', function (ev) {
With that it works.
However it would be better not to use dynamic id attributes all and use CSS classes only. With jQuery methods you can easily find out which is the "current" row that was clicked on (.closest("tr")) and then to .find() the element you need in your formula.
I am new in javascript and facing a problem. I have invoice rows which can be added by pressing on a button. Now i want to calculate the total amount for each row separately(for which the formula is (quantity * price). And the total of all rows combined should become the total of the invoice. The problem is that when I enter the price and quantity in first row, it calculates the total but when I add a new row, it does not calculate the total for new added row after entering the value. Kindly help me in this regard.
function myFunction() {
var x = document.getElementById("price").value;
var y = document.getElementById("quantity").value;
if (x != "") {
document.getElementById("total").value = x * y;
}
}
function add_fields() {
var tableid = document.getElementById('product_table');
var row = document.createElement("tr");
row.innerHTML =
'<td><input type="text" name="price" id="price" oninput="myFunction()"> </td>' +
'<td><input type="text" name="quantity" id="quantity" oninput = "myFunction()" > < /td>' +
'<td><input type="text" name="total" id="total" readonly></td>';
tableid.appendChild(row);
}
table,
tr,
td,
th {
border: 1px black solid;
}
<table>
<thead>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</thead>
<tbody id="product_table">
<tr>
<td><input type="text" name="price" id="price" oninput="myFunction();"></td>
<td><input type="text" name="quantity" id="quantity" oninput="myFunction();"></td>
<td><input type="text" name="total" id="total" readonly></td>
</tr>
</tbody>
<input type="button" name="submit" value="Add Row" onclick="add_fields();">
Use event delegation instead - add a single listener to the container, listen for input events. Then, from the target property of the event, you can get the changed input element. Use .closest to get to the parent <tr>, and then from its descendants, you can get to the associated price, quantity, and total <input>s, and assign values appropriately.
Note that this adds the handler using Javascript, rather than with inline HTML attributes, which are generally considered to be pretty poor practice and can be difficult to manage. Also, duplicate IDs in a single document is invalid HTML - IDs aren't needed anyway here, because the inputs you want are always in a predictable order inside each <tr>. So, you can remove the id and the onclick attributes from the HTML and from the row.innerHTML string:
const table = document.getElementById('product_table');
table.addEventListener('input', ({ target }) => {
const tr = target.closest('tr');
const [price, quantity, total] = tr.querySelectorAll('input');
total.value = price.value * quantity.value;
});
function add_fields() {
var row = document.createElement("tr");
row.innerHTML =
'<td><input type="text" name="price"> </td > ' +
'<td><input type="text" name="quantity"> </td>' +
'<td><input type="text" name="total" readonly></td>';
table.appendChild(row);
}
table,
tr,
td,
th {
border: 1px black solid;
}
<table>
<thead>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</thead>
<tbody id="product_table">
<tr>
<td><input type="text" name="price"></td>
<td><input type="text" name="quantity"></td>
<td><input type="text" name="total" readonly></td>
</tr>
</tbody>
<input type="button" name="submit" value="Add Row" onclick="add_fields();">
I have a page like this:
[http://jsfiddle.net/ph75fggo/]
[http://jsfiddle.net/ph75fggo/5/]//more reliable sample
And I tried to make a simple cashier apps, with help of JavaScript make an auto count on both rows and columns.
This is the result I want to get:
http://jsfiddle.net/wrz8bc10/
My Final Trying: jsfiddle.net
Your Question is not drawing the clear picture of your requirement. As far as I understand, you need to have a gross amount after deducting the discount for each row and the total discounted and net amounts at the end.
First thing that you should do is to assign a common class to each of the child of every tr. It makes your JS code a lot simpler. Otherwise you need write some extra LOC to select specific element.
<tr>
<td><input type='text' class="amount" id='harga2' value='250000' /></td>
<td><input type='text' class="discount" id='diskon2' value='' /></td>
<td><input type='text' class="grossAmount" id='total2' value='' /></td>
</tr>
<tr>
<td><input type='text' class="amount" id='harga2' value='250000' /></td>
<td><input type='text' class="discount" id='diskon2' value='' /></td>
<td><input type='text' class="grossAmount" id='total2' value='' /></td>
</tr>
<tr>
<td><input type='text' class="amount" id='harga2' value='250000' /></td>
<td><input type='text' class="discount" id='diskon2' value='' /></td>
<td><input type='text' class="grossAmount" id='total2' value='' /></td>
</tr>
After that you can use the following function:
function myFunction(){
var amounts = document.getElementsByClassName("amount");
var discounts = document.getElementsByClassName("discount");
var gAmounts = document.getElementsByClassName("grossAmount");
var lv,rowSum,totDis=0,totAmount=0;
for(lv=0;lv>gAmounts.length;lv++){
rowSum += (parseInt(amounts[lv].value)-parseInt(discounts[lv].value));
totAmount += rowSum;
totDis += parseInt(discounts[lv].value);
gAmounts[lv].value = totAmount;
}
}
But if you don't want change your HTML, Then you can use the following code:
function myFunc(){
var lv,rowSum,totDis=0,totAmount=0;
var TRs = document.getElementsByTagName("table")[0].childNodes; //assuming that the table is the first one on your page.
var lv;
for(lv=1;lv<tab.length;lv++){ // starting the counter with 1 as the first child of the table contains headings
rowSum += (parseInt(TRs[lv][0].value)-parseInt(TRs[lv][1].value));
totAmount += rowSum;
totDis += parseInt(TRs[lv][1].value);
TRs[lv].value = rowSum;
}
}
You were getting the elements with ids 'id1' and 'id2' whereas there are no such elements present in your html with those ids, they should be 'harga1' and 'diskon1'. Also, when you write your JS in a function, make sure to call it at the end, but you don't need to write it in a function in this specific case, so here is your solution:
var rows = document.getElementById("myTable").getElementsByTagName("tr").length;
for(var i=1; i<rows; i++){
var harga = parseInt(document.getElementById('harga'+i).value);
var diskon = parseInt(document.getElementById('diskon'+i).value);
var total = harga - diskon;
document.getElementById('total'+i).value = total;
}
Get the number of rows, then keep getting the harga and diskon values one by one.. harga1, harga2, harga3.. ('harga'+i) subtract their values and put them in total1, total2 and total 3.. this will work if you add more rows as well..
See the DEMO here
I have updated the JSFiddle here:
[http://jsfiddle.net/ph75fggo/4/]
This is just one approach at what you are trying to do, where I changed your code as little as possible, and still uses hard coded variable names (instead of the above answer that automatically iterates over all rows). You can use my answer to help simply extend your cashier application.
do you mean like this link?
you can change use the parameters if you want
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<table>
<tr>
<td>Total Harga</td>
<td>Total Diskon</td>
<td>Total Bayar</td>
</tr>
<tr>
<td><input type='text' id='harga1' onchange="dynamic()" value='250000' /></td>
<td><input type='text' id='diskon1' value='50' /></td>
<td><input type='text' id='total1' value='' /></td>
</tr>
<tr>
<td><input type='text' id='harga2' value='250000' /></td>
<td><input type='text' id='diskon2' value='0' /></td>
<td><input type='text' id='total2' value='0' /></td>
</tr>
<tr>
<td><input type='text' id='harga3' value='250000' /></td>
<td><input type='text' id='diskon3' value='0' /></td>
<td><input type='text' id='total3' value='0' /></td>
</tr>
</table>
</body>
<script>
function dynamic(){
var harga1 = document.getElementById('harga1').value;
var diskon1 = document.getElementById('diskon1').value/100;
var totalharga = harga1 - (harga1 * diskon1);
document.getElementById("total1").value = totalharga;
}
</script>
</html>
In my html form I can add extra fileds with javascript. But problem is it's removed the last submitted value when I add another field.
For example:
There is a form fileds called: Ingredient and Quantity. I can add another ingredient and Quantity field by click on "Add more" buttion. Ok suppose, I added a new fields and wrote it's value. But if I again click on the "Add more" buttion it's deleted my last fields value.
**Add more = (Ajouter un autre ingrédient)
Html Code:
<table width="700" border="0" cellspacing="0" cellpadding="5" class="table" style="float:">
<td width="180">Ingrédients</td>
<td>
<input type="text"class="tr" name="ingredients[]" id="ingredients" placeholder="Ingredient"/>
</td>
</tr>
<tr>
<td>Quantité</td>
<td><input name="quantity[]" type="text" id="quantity" placeholder="Quantity" class="tr" /></td>
</tr>
<tr>
<td></td>
<td><input type="button" onclick="addmyrow()" name="add" value="Ajouter un autre ingrédient" /><br/><br/> <div id="row"></td>
</tr>
</table>
Javascript Code:
<script language="javascript">
fields = 0;
function addmyrow() {
if (fields != 10) {
document.getElementById('row').innerHTML += "<input type='text' class='tr' name='ingredients[]' id='ingredients' placeholder='Ingredient'/><br/>";
document.getElementById('row').innerHTML += "<input name='quantity[]' type='text' id='quantity' placeholder='Quantity' class='tr' /><br/>";
fields += 1;
} else {
document.getElementById('row').innerHTML += "<br />Only 10 upload fields allowed.";
document.form.add.disabled=true;
}
}
</script>
Thanks.
When you append contents like this: document.getElementById('row').innerHTML += ...
you're technically replacing the innerHTML with new HTML.
This causes any changes (i.e., form value changes) to be erased.
The correct way is to create brand new DOM elements and then append those elements. What you're doing now is just appending additional HTML.
Here's the corrected version:
<table width="700" border="0" cellspacing="0" cellpadding="5" class="table" style="float:">
<tr>
<td width="180">Ingrédients</td>
<td>
<input type="text"class="tr" name="ingredients[]" id="ingredients" placeholder="Ingredient"/>
</td>
</tr>
<tr>
<td>Quantité</td>
<td><input name="quantity[]" type="text" id="quantity" placeholder="Quantity" class="tr" /></td>
</tr>
<tr>
<td></td>
<td><input type="button" onclick="addmyrow()" name="add" value="Ajouter un autre ingrédient" /><br/><br/> <div id="row"></div>
</td>
</tr>
</table>
<script language="javascript">
fields = 0;
function addmyrow() {
if (fields != 10) {
var newIngredients = document.createElement('input');
var newQuantity = document.createElement('input');
var brTag = document.createElement('br');
newIngredients.setAttribute('type', 'text');
newQuantity.setAttribute('type', 'text');
newIngredients.setAttribute('placeholder', 'Ingredient');
newQuantity.setAttribute('placeholder', 'Quantity');
newIngredients.setAttribute('name', 'ingredients[]');
newQuantity.setAttribute('name', 'quantity[]');
newIngredients.setAttribute('class', 'tr');
newQuantity.setAttribute('class', 'tr');
document.getElementById('row').appendChild(newIngredients);
document.getElementById('row').appendChild(brTag);
document.getElementById('row').appendChild(newQuantity);
document.getElementById('row').appendChild(brTag);
fields += 1;
} else {
document.getElementById('row').innerHTML += "<br />Only 10 upload fields allowed.";
document.form.add.disabled=true;
}
}
</script>
And here's a working fiddle: http://jsfiddle.net/tC7Dm/
changes in innerHTML causes all child DOMs to be destroyed. this link might help
Is it possible to append to innerHTML without destroying descendants' event listeners?
here you go, whoever minusoned me deserves a spoonful of feed.
<script>
function addmyrow() {
var mydiv = document.getElementById("row");
var newcontent = document.createElement('div');
newcontent.innerHTML = "<input type='text' class='tr' name='ingredients[]' id='ingredients' placeholder='Ingredient'/><br/><input name='quantity[]' type='text' id='quantity' placeholder='Quantity' class='tr' /><br/>";
if (fields < 10) {
while (newcontent.firstChild) {
mydiv.appendChild(newcontent.firstChild);
}
fields=fields+1;
}
else {
document.getElementById('row').innerHTML += "<br />Only 10 upload fields allowed.";
document.form.add.disabled=true;
}
}
</script>
#Babu, the reason behind this issue is when you get the existing value with innerHTML it doesn't get the value for input dom elements because the value stored in the property not in the attribute. You could find the same in following links
Inner HTML with input values
So rather than using JS you could try jQuery, Below is a working demo
var fields = 0;
function addmyrow() {
if (fields != 10) {
$("#row").append("<input type='text' class='tr' name='ingredients[]' id='ingredients' placeholder='Ingredient' value='' /><br/>");
$("#row").append("<input name='quantity[]' type='text' id='quantity' placeholder='Quantity' class='tr' /><br/>");
fields += 1;
}
else {
$("#row").append("<br />Only 10 upload fields allowed.");
document.form.add.disabled=true;
}
}
Fiddle Demo
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.