I'm trying to apply a function to input field with ids that contain consequent numbers (ie. price1, price2, price3), etc.
There's no problem with the first row of field that are defined for a start. But further input fields are dynamically added by a jQuery function and their number is not known in advance.
I hoped it would be an easy loop to apply:
var i=1;
$("#quantity"+i).keyup(function() {
var price= $("#price"+i).val();
var quantity= $(this).val();
var value= price*quantity;
var value=value.toFixed(2); /* rounding the value to two digits after period */
value=value.toString().replace(/\./g, ',') /* converting periods to commas */
$("#value"+i).val(value);
});
So far so good - the outcome of the multiplication properly displays in the id="value1" field after the "quantity" field is filled up.
Now further fields should follow the pattern and calculate the value when the quantity is entered - like this:
[price2] * [quantity2] = [value2]
[price3] * [quantity3] = [value3]
etc.
So the code follows:
$('#add_field').click(function(){ /* do the math after another row of fields is added */
var allfields=$('[id^="quantity"]');
var limit=(allfields.length); /* count all fields where id starts with "quantity" - for the loop */
for (var count = 2; count < limit; count++) { /* starting value is now 2 */
$("#quantity"+count).keyup(function() {
var cena = $("#price"+count).val();
var quantity= $("#quantity"+count).val();
var value= price*quantity;
var value=value.toFixed(2);
value=value.toString().replace(/\./g, ',')
$("#value"+count).val(value);
});
}
});
The problem is that all further "value" fields are only calculated when "quantity2" is (re)entered and the "value2" is not calculated at all.
I guess there's a mistake while addressing fields and/or triggering the calculation.
How should I correct the code?
Just in case the "add_field" function is needed to solve the problem:
$(document).ready(function(){
var i=1;
$('#add_field').click(function(){
i++;
$('#offer').append('<tr id="row'+i+'">
<td><input type="text" name="prod_num[]" id="prod_num'+i+'" placeholder="Product number (6 digits)"></td><td><input type="text" name="prod_name[]" disabled></td>
<td><input type="text" name="cena[]" id="price'+i+'" placeholder="Enter your price"></td>
<td><input type="text" name="quantity[]" id="quantity'+i+'" placeholder="Enter quantity"></td>
<td><input type="text" name="value[]" id="value'+i+'" disabled></td>
<td><button type="button" name="remove_field" id="'+i+'" class="button_remove">X</button></td></tr>');
});
Incrementing IDs is a lot more trouble than it is worth, especially when you start removing rows as well as adding them.
This can all be done using common classes and traversing within the specific row instance.
To account for future rows use event delegation.
Simplified example:
// store a row copy on page load
const $storedRow = $('#myTable tr').first().clone()
// delegate event listener to permanent ancestor
$('#myTable').on('input', '.qty, .price', function(){
const $row = $(this).closest('tr'),
price = $row.find('.price').val(),
qty = $row.find('.qty').val();
$row.find('.total').val(price*qty)
});
$('button').click(function(){
// insert a copy of the stored row
// delegated events will work seamlessly on new rows also
const $newRow = $storedRow.clone();
const prodName = 'Product XYZ';// get real value from user input
$newRow.find('.prod-name').text(prodName)//
$('#myTable').append($newRow)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Add row</button>
<table id="myTable">
<tr>
<td class="prod-name">Product 1</td>
<td>Qty:<input type="number" class="qty" value="0"></td>
<td>Price:<input type="number" class="price" value="0"></td>
<td>Total:<input type="text" class="total" value="0" readonly></td>
</tr>
<tr>
<td class="prod-name">Product 2</td>
<td>Qty:<input type="number" class="qty" value="0"></td>
<td>Price:<input type="number" class="price" value="0"></td>
<td>Total:<input type="text" class="total" value="0" readonly></td>
</tr>
</table>
Understanding Event Delegation
The first thing to consider is that you can get the length of a selector. So for example:
var count = $("input").length;
If there is one, value here would be 1. if there are four, the value would be 4.
You can also use .each() option to itereate each of the items in the selector.
$('#add_field').click(function(){
var allFields = $('[id^="quantity"]');
allFields.each(function(i, el){
var c = i + 1;
$(el).keyup(function() {
var price = parseFloat($("#price" + c).val());
var quantity = parseInt($(el).val());
var value = price * quantity;
value = value.toFixed(2);
value = value.toString().replace(/\./g, ',');
$("#value" + c).val(value);
});
});
});
You could also create relationship based on the ID itself.
$(function() {
function calcTotal(price, qnty) {
return (parseFloat(price) * parseInt(qnty)).toFixed(2);
}
$('#add_field').click(function() {
var rowClone = $("#row-1").clone(true);
var c = $("tbody tr[id^='row']").length + 1;
rowClone.attr("id", "row-" + c);
$("input:eq(0)", rowClone).val("").attr("id", "prod_num-" + c);
$("input:eq(1)", rowClone).val("").attr("id", "price-" + c);
$("input:eq(2)", rowClone).val("").attr("id", "quantity-" + c);
$("input:eq(3)", rowClone).val("").attr("id", "value-" + c);
$("button", rowClone).attr("id", "remove-" + c);
rowClone.appendTo("table tbody");
});
$("table tbody").on("keyup", "[id^='quantity']", function(e) {
var $self = $(this);
var id = $self.attr("id").substr(-1);
if ($("#price-" + id).val() != "" && $self.val() != "") {
$("#value-" + id).val(calcTotal($("#price-" + id).val(), $self.val()));
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="add_field">Add Field</button>
<br />
<h2>Product</h2>
<table>
<thead>
<tr>
<td>Number</td>
<td>Name</td>
<td>Price</td>
<td>Quantity</td>
<td>Total</td>
<td></td>
</thead>
<tbody>
<tr id="row-1">
<td><input type="text" name="prod_num[]" id="prod_num-1" placeholder="Product number (6 digits)"></td>
<td><input type="text" name="prod_name[]" disabled></td>
<td><input type="text" name="cena[]" id="price-1" placeholder="Enter your price"></td>
<td><input type="text" name="quantity[]" id="quantity-1" placeholder="Enter quantity"></td>
<td><input type="text" name="value[]" id="value-1" disabled></td>
<td><button type="button" name="remove_field" id="remove-1" class="button_remove">X</button></td>
</tr>
</tbody>
</table>
Related
Could someone please tell me how I can use the index in this situation?
I have a text field, which is my multiplication factor
<input type="text" id="value">
And I have a table that has 2 fields arranged in the same tr
One with a fixed value
And one that must be the result of multiplying these two values.
Example:
In input I set value = 2
Field Value2 = Value 1 * 2
Value 1
Value 2
3
6
4
8
My jQuery function looks like this:
$( "#btn" ).on( "click", function()
{
let vlUS = $('#value').val()
$("table > tbody > tr > td > input")
.each(function (index) {
let vl1 = $('.val1').val()
let vl2 = vl1 * vlUS
$('.val2').val(vl2)
});
});
Using this way, assigns the same value to all "value2" fields
How can I use index to tune the process?
Loop over the rows and use each row instance to find() the specific inputs within that row
$("#btn").on("click", function() {
let vlUS = $('#value').val();
$("table > tbody > tr").each(function(index) {
const $row = $(this);
let vl1 = $row.find('.val1').val()
let vl2 = vl1 * vlUS
$row.find('.val2').val(vl2);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">
Calculate
</button> US: <input id="value" value="5" />
<table>
<tr>
<td><input type="text" class="val1" value="3"></td>
<td><input type="text" class="val2"></td>
</tr>
<tr>
<td><input type="text" class="val1" value="6"></td>
<td><input type="text" class="val2"></td>
</tr>
</table>
Consider the following code.
$("#btn").on("click", function() {
$("table tbody tr").each(function(index, elem) {
$(".val2", elem).val(parseInt($(".val1", elem).val()) * parseInt($("#value").val()));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">Calculate</button> US: <input id="value" value="5" />
<table>
<tr>
<td><input type="text" class="val1" value="3"></td>
<td><input type="text" class="val2"></td>
</tr>
<tr>
<td><input type="text" class="val1" value="6"></td>
<td><input type="text" class="val2"></td>
</tr>
</table>
Simply reduces the operation to one line. Also ensures that if the User enters a Letter; it won't fail.
It is hard to explain, you can see a DEMO HERE
I have a products table that dynamically creates/deletes new lines of products. I also have a totals table that totals up the totals of each line together.
In that totals box, I have a travel box I want to add to the grand total, but the issue I am having is the travel input is outside the table that is totaling all the values. I can replace the total with a new total, but I can not seem to call the sub total, add the travel and output a grand total.
HTML
<table class="order-details">
<tbody>
<tr>
<td><input type="text" value="" name="" placeholder="Work Description" class="wei-add-field description 1"/></td>
<td><input type="text" value="" name="" placeholder="QTY" class="wei-add-field quantity 1" /></td>
<td><input type="text" value="" name="" placeholder="$0.00" class="wei-add-field unit-price 1"/></td>
<td><input type="text" value="" name="" placeholder="$0.00" class="wei-add-field price-total 1" id=""/></td>
<td> </td>
</tr>
</tbody>
</table>
<div class="wei-add-service">Add Item</div>
<table class="wei-add-totals">
<tr>
<td width="50%">Sub Total</td>
<td width="50%" class="wie-add-subtotal"> </td>
</tr>
<tr class="alternate travel">
<td>Travel</td>
<td><input type="text" value="" placeholder="0.00" class="wei-add-field travel" /></td>
</tr>
<tr>
<td>Taxes</td>
<td><input type="text" value="" placeholder="0.00" class="wei-add-field wie-total-taxes" id="wei-disabled" disabled/> </td>
</tr>
<tr class="alternate total">
<td>Total</td>
<td><input type="text" value="" placeholder="0.00" class="wei-add-field wie-grand-total" id="wei-disabled" disabled/></td>
</tr>
</table>
Javascript
var counter = 1;
var testArray = [ 2,3,4,5];
jQuery('a.wei-add-service-button').click(function(event){
event.preventDefault();
counter++;
var newRow = jQuery('<tr><td><input type="text" class="wei-add-field description ' + counter + '"/></td><td><input type="text" class="wei-add-field quantity ' + counter + '" /></td><td><input type="text" class="wei-add-field unit-price ' + counter + '"/></td><td><input type="text" value="" name="" placeholder="$0.00" class="wei-add-field price-total ' + counter + '" id=""/></td><td>X</td></tr>');
jQuery('table.order-details').append(newRow);
});
jQuery('table.order-details').on('click','tr a',function(e){
e.preventDefault();
var table = $(this).closest('table');
jQuery(this).parents('tr').remove();
reCalculate.call( table );
});
jQuery('table.order-details').on("keyup", "tr", reCalculate);
function reCalculate() {
var grandTotal = 0;
jQuery(this).closest('table').find('tr').each(function() {
var row = jQuery(this);
var value = +jQuery( ".unit-price", row ).val();
var value2 = +jQuery( ".quantity", row ).val();
var total = value * value2;
grandTotal += total;
jQuery( ".wei-add-field.price-total", row ).val( '$' + total.toFixed(2) );
});
jQuery(".wie-add-subtotal").text( '$' + grandTotal.toFixed(2));
}
I don't think, given the task of creating this, I would have chosen to do it in the way you did.
However, using your existing code you can bind the Travel value on change, paste, or keyup and run a function on any of those actions. Within that function I have removed the special character ($) from ".wie-grand-total" using a regex and converted the value of ".wie-grand-total" to a float using parseFloat. I also converted the Travel value to a float using parseFloat. I then added them together and made the sum your new value for "wie-grand-total".
/* NEW SINCE COMMENTS */
//Add to your HTML New table
<table class="order-details">
<tbody>
<tr>
<td><input type="text" value="" name="" placeholder="Work Description" class="wei-add-field description 1"/></td>
<td><input type="text" value="" name="" placeholder="QTY" class="wei-add-field quantity 1" /></td>
<td><input type="text" value="" name="" placeholder="$0.00" class="wei-add-field unit-price 1"/></td>
<td><input type="text" value="" name="" placeholder="$0.00" class="wei-add-field price-total 1" id=""/></td>
/* NEW SINCE COMMENTS*/
<td><input type="text" id="travelHid" value=""></td>
<td> </td>
</tr>
</tbody>
</table>
/* NEW SINCE COMMENTS */
$('#travelHid').hide();
var travelVal = 0;
function updateTravelVal(travelVal){
var travelVal = travelVal;
$('#travelHid').val(travelVal);
};
updateTravelVal();
$("#travelVis").bind("change paste keyup", function() {
var noChars = jQuery(".wie-grand-total").val().replace(/[^0-9.]/g, "");
var newTot = parseFloat(noChars) + parseFloat($(this).val());
jQuery(".wie-grand-total").val( '$' + newTot.toFixed(2));
//added error checking
var checkError = jQuery(".wie-grand-total").val( '$' + newTot.toFixed(2));
//if the value that would go in input is NaN then use travelVal
//since there is no value in .wie-grand-total yet
if (typeof checkError !== "string") {
jQuery(".wie-grand-total").val( '$' + travelVal.toFixed(2))
} else if (typeof checkError === "string") {
jQuery(".wie-grand-total").val( '$' + newTot.toFixed(2))
}
/* NEW SINCE COMMENTS */
updateTravelVal(travelVal);
});
A fiddle for demonstration (now with hiddenVal per comment)
http://jsfiddle.net/chrislewispac/wed6eog0/3/
Only potential problems here are it only runs when you change, paste, or key up the value in #TravelVis.
/EXPLAINED SINCE COMMENTS/
It the html I added a td with input. Input id="travelHid". I then make that invisible by applying jQuery method .hide(). I then exposed travelVal to global scope an initiated it with a value of zero then created a function to update that value.
Within that function I set the value to the argument travelVal or to 0 if there are no args. I then immediately call it.
Then, I added a call to that function with the arg travelVal from our bind function to update it if a value is present.
And finally:
Just add a row to the table with preset value of Travel and Quant 1.
http://jsfiddle.net/chrislewispac/xntn7p5p/5/
So I have a base Hour input field and I'm trying to validate the other input fields so that once the base hour is added the other input values can only be as large as the first base rate Hours column (first input). Or put another way the one input field becomes the max number value once it is entered. So if the base is 12 for the Hours column the second and third rate can be no larger than 12. The tricky part is add new row feature means all new rows for the hour column have to adhere to the rule as well. I have been trying to figure it out for a bit, any help would be appreciated.
Here is the fiddle: http://jsfiddle.net/uuzhuom9/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
$('#calculate').on('click', function() {
$('.hours-table tr').each(function() {
var hours = $(this).find('input.hours').val();
var rate = $(this).find('input.rate').val();
var dateTotal = (hours * rate);
$(this).find('input.date-total').val(dateTotal);
// total += parseInt($("input.date-total").val());
var sum = 0;
//iterate through each textboxes and add the values
$("input.date-total").each(function () {
//add only if the value is number
if (!isNaN($(this).val()) && $(this).val().length != 0) {
sum += parseFloat(this.value);
}
});
if (sum < 0) {
alert("Total can't be negative");
$('#grandtotal-new').val('');
} else {
$("#grandtotal-new").val(sum)
}
}); //END .each
return false;
}); // END click
});
$(function(){
var counter = 4;
$('a.add-row').click(function(event){
event.preventDefault();
counter++;
var newRow = jQuery('<tr><td><input type="text" value="" /></td><td><input type="text" class="hours" name="rate-0' + counter + '"/></td><td><input type="text" class="rate" name="rate-0' + counter + '"/></td><td><input type="text" class="date-total" readonly name="date-total-0' + counter + '"/></td></tr>');
$('table.hours-table').append(newRow);
});
});
</script>
The html is:
<table class="hours-table">
<tr>
<th>Item</th>
<th>Hours</th>
<th>Hourly Rate</th>
<th>Total</th>
</tr>
<tr>
<td>Base Rate:</td>
<td class="hours"><input type="number" class="hours" id="base-hours" name="hours-01" max="???" min="???" value="" /></td>
<td class="rate"><input min="0" class="rate" name="rate-01" value="200" readonly /></td>
<td class="date-total"><input type="text" class="date-total" name="date-total-0" readonly /></td>
</tr>
<tr>
<td>Second Rate:</td>
<td class="hours"><input type="number" class="hours" name="hours-02" max="???" min="???" value="" /></td>
<td class="rate"><input type="text" class="rate" name="rate-02" value="-20" readonly /></td>
<td class="date-total"><input type="text" class="date-total" name="date-total-1" readonly /></td>
</tr>
<tr>
<td>Third Rate:</td>
<td class="hours"><input type="number" class="hours" name="hours-03" max="???" min="???" value="" /></td>
<td class="rate"><input type="text" class="rate" name="rate-03" value="10" readonly /></td>
<td class="date-total"><input type="text" class="date-total" name="date-total-2" readonly/></td>
</tr>
</table>
Add New Rule<br />
<button type="button" id='calculate' class="btn btn-inverse btn- mini">Calculate</button>
The Grand total is: <input type="number" id='grandtotal-new' min="???"/>
Just validate them on blur of each .hours input as below:
DEMO
$(document).on('blur','.hours',function(){
var current=$(this);
if(!(current).is('input.hours:first'))
{
if(current.val()>$('input.hours:first').val())
current.val('');
}
});
This will check value of input on blur and clears it if it is greater than first one
UPDATE:
DEMO
parse the value before checking as below:
$(document).on('blur','.hours',function(){
var current=$(this);
if(!(current).is('input.hours:first'))
{
if(parseInt(current.val())>parseInt($('input.hours:first').val()))
current.val('');
}
});
UPDATE 2
Based on OPs comments here is the way to achieve the requirements mentioned by him.
DEMO
$(document).on('blur','.hours',function(e){
var current=$(this);
var base=$('input.hours:first');
var total=0;
var other=$('input.hours:not(:first)');
if(base.val()==="")
{
alert('Enter Base First');
current.val('');
base.focus();
e.stopPropagation();
return;
}
$.each($(other),function(index,value){
if(value.value!=="")
total+=parseInt(parseInt(value.value));
});
console.log(total);
if(!(current).is(base))
{
if(parseInt(current.val())>parseInt(base.val()))
{
current.val('');
}
else if(total>parseInt($('input.hours:first').val()))
current.val('');
}
});
add this at the beginning of your jquery script.
this will limit the other hours input to whatever is on base-hours, including newly added rows.
var baseRate = 0;
$(".hours-table").on("input","input.hours",function() {
if ($(this).attr('id') == 'base-hours'){
baseRate = $(this).val();
}else if ($(this).val() > baseRate){
$(this).val(baseRate);
}
});
and then further down below you have a syntax/logic error on your add row function. replace this line with this corrected line, and you might wanna move your counter++ after this line.
var newRow = jQuery('<tr><td><input type="text" value="" /></td><td><input type="text" class="hours" name="rate-0' + counter + '"/></td><td><input type="text" class="rate" name="rate-0' + counter + '"/></td><td><input type="text" class="date-total" readonly name="date-total-0' + counter + '"/></td></tr>');
check this jsfiddle - http://jsfiddle.net/uuzhuom9/8/
My Java Script Code
<script>
$(function(){
$('#addRow').click(function(){
var html = $('#row_template').html();
$('#dataTable').append(html);
$(".tablerow").each(function(index) {
$(this).html(index + 1);
});
});
$('#deleteRow').click(function(){
$('#dataTable .mychkbox:checked').parents('tr').remove();
});
$('#dataTable').on('change','.select-desc',function(){
var cur_val = $(this).val();
$(this).parents('tr').find('input[name="rate[]"]').val(cur_val);
});
$('#dataTable').on('keyup','input[name="qty[]"]', function(){
var qty = +$(this).val();
var unit = +$(this).parents('tr').find('input[name="rate[]"]').val();
$(this).parents('tr').find('input[name="amt[]"]').val(qty*unit);
var totamt = 0 ;
var theTbl = document.getElementById('dataTable');
for(var i=0;i<theTbl.length;i++)
{
for(var j=0;j<theTbl.rows[i].cells.length;j++)
{
totamt = totamt + theTbl.rows[i].cells[4].InnerHTML;
}
}
});
});
</script>
My HTML Code is
<!DOCTYPE html>
<html>
<div class="left">
<h2><span class="orange">Work Order Items</span></h2>
<table>
<tr>
<td><input type="button" value="Add Row" id="addRow" /></td>
<td><input type="button" value="Remove Row" id="deleteRow" /></td>
</tr>
</table>
</div>
<table id="dataTable" class="form" border="0" width='100%'>
<tr>
<td></td>
<td>No</td>
<td>Item Description</label></td>
<td>Qty</td>
<td>Rate</td>
<td>Amount</td>
<td>Cert No</td>
<td>C Date</td>
</tr>
</table>
<table id="row_template" style="display:none">
<tr>
<td><input type="checkbox" name="chk[]" class="mychkbox" /></td>
<td class="tablerow"></td>
<td>
<?php
$sql = "SELECT itrate,CONCAT(itname,'|',itcode) as mname FROM ITMAST ";
$result = mysql_query($sql) or die(mysql_error());
echo "<select name='itname[]' id='itname' class='select-desc' >";
echo "<option value=''>-- Select Item --</option>";
while ($row = mysql_fetch_array($result))
{
echo "<option value = '{$row['itrate']}'";
if ($pitcode == $row['itrate'])
echo "selected = 'selected'";
echo ">{$row['mname']}</option>";
}
echo "</select>";
?>
</td>
<td><input type="text" name="qty[]" id="qty" size="6" class='rightJustified'></td>
<td><input type="text" name="rate[]" id="rate" size="8" class='rightJustified' readonly></td>
<td><input type="text" name="amt[]" id="amt" size="9" class='rightJustified' readonly></td>
<td><input type="text" maxlength="10" size="8" name="txtcertno[]"></td>
<td><input type="date" maxlength="10" size="10" name="txtcdate[]"></td>
</tr>
</table>
</html>
I am trying to take total of amount column i.e. amt[] after each entry of a row, but I am not getting it properly, I have written Javascript function for the same but some thing may be wrong in it
I did not correct all of your mistakes,
You should check #Samurai answer for more details (such as use of the 'id' and other things)
Main problem was, as I said in comment, use of innerHTML which returned "
another thing, your theTbl var was not good, you could never call .length on it. To solve that, you had to handle it this way :
var totamt = 0 ;
var theTbl = $('#dataTable');
//You are using jquery, so use jquery selectors...
var trs = theTbl.find("input[name='amt[]']");
//find there the AMT[] INPUTS, not the rows...
console.log("how many amt inputs? : "+trs.length);
for(var i=0;i<trs.length;i++)
{
//fetch the inputs, and make your calculations here
console.log("amount from row "+i+" = "+trs[i].value);
//do not forget, as Samurai said, to convert html to numeric...
$("#total").html(totamt+=parseFloat(trs[i].value));
}
Here is a working solution :
http://jsfiddle.net/nxm0ye54/20/
First to point out a few mistakes:
$('#row_template').html(): browsers automatically add tbody to the table, so you end up having multiple tbody in your main table which of course won't cause any problem on its own, if that's the desired output.
You're misusing ID. Each tr has multiple td with inputs that share the same ID. Instead you should use class.
To calculate the total amount you're getting the innerHTML of the cells which don't hold a number, but an input element. Instead you want the value these input elements are holding.
You need to convert the values to numbers before doing math on them, otherwise it will assume they're string and just put them beside each other. (e.g. 0+1+2 = 012 and not 3). You should use parseInt or parseFlout which the latter suits this case better.
A few modifications to your code:
$('#addRow').click(function () {
var html = $('#row_template tbody').html();
$('#dataTable tbody').append(html);
And - since you're using jQuery - I completely changed the calculation to a jQuery version:
//gt(0) cause the first row contains headers
//eq(5) cause we want the 6th cell (Amount)
var totamt = 0;
$('#dataTable tr:gt(0)').each(function() {
var newAmt = $(this).find('td:eq(5) input[type=text]').val();
totamt += parseFloat(newAmt);
});
I have a dynamically created form in that a user can click "add row" and get a new element in the form.
some of the elements are quantity and price. I want to change values based on what users enter. so if he chooses qty=4 and price=10 i want amount to =40.
I dont know what to use as the selector for price or amount since input ids are dynamically generated.
var form = "<tr><td>Quantity</td>
<td><input class='qty' type='text' id='qty[]' name='qty[]'></td>";
form += "<td>Part Num</td>
<td><input type='text' id='part[]' name='part[]'></td>";
form += "<td>Description</td>
<td><input class='desc' type='text' id='desc[]' name='desc[]'></td>";
form += "<td>Unit Price</td>
<td><input type='text' id='price[]' name='price[]'></td>";
form += "<td>Amount</td>
<td><input type='text' id='amount[]' name='amount'></td></tr>";
$('#addItem').click(function(){
$('#itemsTable').append(form);
});
$(document).on('change','.qty',function(){
//What can i use as a selector for value_of_qty and value_of_price here???
//var total = $(value_of_qty) * $(value_of_price);
//$(id_of_amount).val(total);
});
on form submissions i see the following:
[qty] => Array
(
[0] => asdfdasf
[1] => asdfdasf
)
and so on....
You have (roughly) this structure:
<tr>
<td><input class="qty"></td>
<td><input name="price[]"></td>
</tr>
So, given that you have the .qty input, all you need to do is rise to the tr and get its input[name='price[]']. In code:
$(document).on('change','.qty',function(){
var $qty = $(this);
var $price = $qty.closest("tr").find("input[name='price[]']");
});
As I described in my comment, your HTML is invalid because you have duplicate ids. You should dynamically generate the HTML you append to the parent element, and assign a unique id value with each appendage. Here's what I would do:
var g_ROWNUM = 1;
$('#addItem').click(function() {
var form = '\
<tr>\
<td>Quantity</td><td><input class="qty" type="text" id="qty_${num}" name="qty[]"></td>\
<td>Part Num</td><td><input type="text" id="part_${num}" name="part[]"></td>\
<td>Description</td><td><input class="desc" type="text" id="desc_${num}" name="desc[]"></td>\
<td>Unit Price</td><td><input type="text" id="price_${num}" name="price[]"></td>\
<td>Amount</td><td><input type="text" id="amount_${num}" name="amount[]"></td>\
</tr>\
'.replace(/\$\{num\}/g,g_ROWNUM++);
$('#itemsTable').append(form);
});
$(document).on('change', '.qty', function() {
var qtyInput = $(this);
var num = qtyInput.attr('id').replace(/^qty_/,'');
var priceInput = $('#price_'+num);
var amountInput = $('#amount_'+num);
var total = qtyInput.val()*priceInput.val();
amountInput.val(total);
});
As you can see, this allows you to extract the generated number and use it to retrieve the price and amount elements in the same row as the changed quantity element, and then apply any dynamic changes you want to the elements in that row.
http://jsfiddle.net/p6wrkne4/1/
you should restructure your html by adding classes like this:
<tr class="tableRow">
<td>Quantity</td>
<td><input class='qty' type='text' id='qty[]' name='qty[]'/></td><td>Part Num</td>
<td><input type='text' id='part[]' name='part[]'/></td>
<td>Description</td>
<td><input class='desc' type='text' id='desc[]' name='desc[]'/></td>
<td>Unit Price</td>
<td><input type='text' class="price" id='price[]' name='price[]'/></td>
<td>Amount</td>
<td><input type='text' class="amount" id='amount[]' name='amount'/></td>
</tr>
$(document).on('change', '.qty', function() {
var qty = $(this).val();
var price = $(this).closest('.tableRow').find('.price').val();
var total = qty * price;
$(this).closest('.tableRow').find('.amount').val(total);
});
Try this code:
$(document).on('change','.qty',function(){
var qtyInput = $(this);
var price = qtyInput.closest("tr").find("input[name='price[]']").val();
var amount = qtyInput.val() * price;
qtyInput.closest("tr").find("input[name=amount]").val(amount);
});