I'm adding table rows dynamically with a button "Add New Line". When clicked, this fires off a jQuery event which creates a new table row containing form fields. The form fields allow numeric values only.
When a value gets entered into the field, it calculates VAT and Line Total amounts. These totals then get appended to the closest()
table row <tr>
.
The code works fine for the first row. As soon as a new row is added, the code stops working and values are calculated for the second row.
I believe this has something to do with the fact the rows (and form fields) are dynamically created by jQuery and injected into the page, so closest()
cant't find them.
Whats the solution to this?
Thanks in advance.
Javascript:
$(document).ready(function () {
var counter = 2;
$("#addRow").on("click", function ()
{
var newRow = $("<tr>");
var cols = "";
cols += '<td>' + counter + '</td>';
cols += '<td><textarea class="form-control" name="description[' + counter + ']"></textarea></td>';
cols += '<td><input type="text" class="form-control line-quantity" name="quantity[' + counter + ']" onkeypress="return isNumberKey(event)"></td>';
cols += '<td><input type="text" class="form-control line-price" name="unit_price[' + counter + ']" onkeypress="return isNumberKey(event)"></td>';
cols += '<td class="line_vat">£0.00</td>';
cols += '<td class="line_total">£0.00</td>';
cols += '<td><input type="button" class="ibtnDel btn btn-md btn-danger" value="Delete"></td>';
newRow.append(cols);
$("table.table-striped").append(newRow);
counter++;
});
$("table.table-striped").on("click", ".ibtnDel", function (event)
{
$(this).closest("tr").remove();
counter -= 1
});
// Update line vat & subtotal
$(".line-quantity, .line-price").on("blur", function (event)
{
var line_qty = 0;
var line_price = 0;
var line_subtotal = '0.00';
var vat = '0.00';
var line_total = '0.00';
line_qty = $(this).closest('#quote_table').find('input.line-quantity').val();
line_price = $(this).closest('#quote_table').find('input.line-price').val();
// calculate total line price
line_subtotal = line_price*line_qty;
// Calculate VAT
vat = line_subtotal*1.2-line_subtotal;
// Line total
line_total = line_subtotal+vat;
// Update view with totals
$(this).closest('tr').find('td.line_vat').html(vat.toLocaleString('en-US', {style: 'currency',currency: 'GBP'}));
$(this).closest('tr').find('td.line_total').html(line_total.toLocaleString('en-US', {style: 'currency',currency: 'GBP'}));
// Calculate totals at end of table
});
});
function isNumberKey(evt){
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode != 46 && charCode > 31 && (charCode < 48 || charCode > 57))
return false;
return true;
}
HTML:
<form method="post" action="{{ url('cp/quotes/create') }}">
{{ csrf_field() }}
<div class="form-group">
@if($contacts->isEmpty())
<a href="/cp/contacts/create">Create first contact</a>
@else
<label for="contact">Contact</label>
<!-- Get the selected contact and fetch properties -->
<select class="form-control selectpicker show-tick" data-live-search="true" id="contact" name="contact" data-live-search-placeholder="Find contact...">
<option value="">Select a contact...</option>
@foreach($contacts as $contact)
<option data-tokens="{{ $contact->id }}" value="{{ $contact->id }}">{{ $contact->contact_name }} ({{ $contact->first_name }} {{ $contact->last_name }})</option>
@endforeach
</select>
<!-- List contact properties -->
<div class="btn-group-vertical property_list" role="group" aria-label="Property" id="property_list"></div>
@endif
</div>
<div class="form-group">
<label class="control-label" for="raised_date">
Date
</label>
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input class="form-control" id="raised_date" name="raised_date" type="text"/>
</div>
</div>
<div class="form-group">
<label class="control-label" for="raised_date">
Expiry Date
</label>
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input class="form-control" id="expiry_date" name="expiry_date" type="text"/>
</div>
</div>
<table class="table table-striped" id="quote_table">
<thead>
<tr>
<th scope="col">Item #</th>
<th scope="col">Description</th>
<th scope="col">Quantity</th>
<th scope="col">Unit Price</th>
<th scope="col">VAT</th>
<th scope="col">Amount</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><textarea class="form-control" name="description[]"></textarea></td>
<td><input class="form-control line-quantity" name="quantity[]" type="text" onkeypress="return isNumberKey(event)"></td>
<td><input class="form-control line-price" name="unit_price[]" type="text" onkeypress="return isNumberKey(event)"></td>
<td class="line_vat">£0.00</td>
<td class="line_total">£0.00</td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-end">Subtotal</td>
<td colspan="2" class="subtotal">£0.00</td>
</tr>
<tr>
<td colspan="5" class="text-end h3">Total</td>
<td colspan="2" class="total h3">£0.00</td>
</tr>
</tfoot>
</table>
<a class="btn btn-warning addRow" href="#" id="addRow">Add Line +</a>
<div class="form-group">
<br /><button type="submit" class="btn btn-success">Save Quote</button>
</div>
</form>
Application screenshot: