Reputation: 84
I have a table in which there are 5 rows already, I have added js code so that when a user types something in the last row, it gets cloned (works fine) but when a user types something in the cloned row, it's not getting cloned. Can someone, please help me as to why it's not working?
$(document).ready(function() {
$(".keynum").change(function(event) {
$("#frmOK").val("1");
var pid = $('#p').val();
lastval = $(".keynum").last().val();
if (lastval != "") {
var $tableBody = $('#tblKeyNumQty').find("tbody"),
$trLast = $tableBody.find("tr:last"),
$trNew = $trLast.clone();
$trLast.after($trNew);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tblKeyNumQty" class="table table-responsive table-striped table-bordered">
<tbody>
<tr>
<th align="center">Key Number</th>
<th align="center">Quantity</th>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum" value="" onkeypress="return event.keyCode != 13;" /></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2" onkeypress="return event.keyCode != 13;" /></td>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum" value="" onkeypress="return event.keyCode != 13;" /></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2" onkeypress="return event.keyCode != 13;" /></td>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum" value="" onkeypress="return event.keyCode != 13;" /></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2" onkeypress="return event.keyCode != 13;" /></td>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum" value="" onkeypress="return event.keyCode != 13;" /></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2" onkeypress="return event.keyCode != 13;" /></td>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum" value="" onkeypress="return event.keyCode != 13;" /></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2" onkeypress="return event.keyCode != 13;" /></td>
</tr>
</tbody>
</table>
Upvotes: 1
Views: 298
Reputation: 43880
When dealing with dynamically added DOM elements, you must delegate events to an ancestor element that has existed since the webpage was loaded. In this situation, the <form>
(not provided in HTML of question -- but evident that one exists by the jQuery provided). Even though the <table>
(even document
for that matter -- although not recommended) is also an ancestor element of all <input>
s, the "change"
event only applies to <form>
elements and form controls (ex. <input>
, <select>
, etc.).
99% of the time the .on()
method is the best way to delegate events. The following is the most effective pattern:
$("selectorOfAncestor").on("eventType", "selectorOfTargets", eventHandler);
// So if you had <form id="OK"> wrapped around the <table>...
$("#OK").on("change", ".keynum:last", cloneLast)
// When defining the event handler (ex. function cloneLast(e) {... ) ".keynum:last" = this
jQuery allows you to conveniently "blanket over" many elements in a very flexible and accurate way -- so you should never use on-event attributes like this abomination:
<input ... onkeypress="return event.keyCode != 13;">
Use one line of code -- not 100 lines of the same code:
$('input').on('keypress', function(e) {
return e.keyCode != 13
});
Also, note that I corrected the <table>
a little by wrapping a <thead>
around the <th>
and applied the Bootstrap class .text-center
to the <thead>
. The attribute [align]
is deprecated and if you don't have Bootstrap, use the CSS property text-align
instead.
One more piece of advice: If you place your jQuery/JavaScript before the closing body tag (ie </body>
), then you don't need to wrap everything in $(document).ready({...})
. Regardless of whether you do or not, placing <script>
before the closing </body>
tag is 99% the most efficient place to have it.
$('#OK').on('change', '.keynum:last', cloneLast);
function cloneLast(e) {
if ($(this).val() !== '') {
$(this).closest('tr').clone().appendTo($(this).closest('tbody'));
}
}
$('input').on('keypress', function(e) {
return e.keyCode != 13
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<form id='OK'>
<table id="tblKeyNumQty" class="table table-responsive table-striped table-bordered">
<thead class='text-center'>
<tr>
<th>Key Number</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum"></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2"></td>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum"></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2"></td>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum"></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2"></td>
</tr>
<tr>
<td><input name="keynum[]" placeholder="SKU-123" class="form-control keynum"></td>
<td><input name="qty[]" type="number" min="2" class="form-control" value="2"></td>
</tr>
</tbody>
</table>
</form>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
Upvotes: 2
Reputation: 1317
Add the change handler to newly created table rows as well:
function keynumChange(event) {
$("#frmOK").val("1");
var pid = $('#p').val();
lastval = $(".keynum").last().val();
if (lastval != "") {
var $tableBody = $('#tblKeyNumQty').find("tbody"),
$trLast = $tableBody.find("tr:last"),
$trNew = $trLast.clone();
$trNew.change(keynumChange); // <- mind this!
$trLast.after($trNew);
}
}
$( document ).ready(function() {
$( ".keynum" ).change(keynumChange);
});
Since they were added after the $(document).ready
, this will not apply to those newly added rows by default.
Upvotes: 2