I have a simple table that by default shows a single row, with an add button for users to add additional rows if required. I have a delete icon showing in the last column for users to delete a row, however this only works for the first table row and doesn't work for any rows the user has added themselves.
I understand the issue is in this answer and relates to the objects that exist when the page is first loaded, but I can't work out how to implement that solution in my example as I'm only just learning Javascript and jQuery here.
Here's a sample of how this looks:
$(document).ready(function() {
$("#addRow").click(function() {
var markup = "<tr><td><input type=\"text\" class=\"form-control\" autocomplete=\"off\" placeholder=\"Serial\" name=\"serial\"></td><td></td><td></td><td></td><td><span class=\"glyphicon glyphicon-trash\"></span></td></tr>";
$("#shipmentConsignment").append(markup);
});
// Find and remove selected table rows
$("#deleteRow").click(function() {
$(this).closest('tr').remove();
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<table id="shipmentConsignment" class="table table-condensed table-striped table-bordered">
<thead>
<th class="text-center" scope="col" width="20%">Serial</th>
<th class="text-center" scope="col" width="15%">ID</th>
<th class="text-center" scope="col" width="15%">Code</th>
<th class="text-center" scope="col" width="45%">Description</th>
<th class="text-center" scope="col" width="5%"></th>
</thead>
<tbody>
<tr>
<td><input type="text" class="form-control" autocomplete="off" placeholder="Serial" name="serial"></td>
<td></td>
<td></td>
<td></td>
<td id="deleteRow"><span class="glyphicon glyphicon-trash"></span></td>
</tr>
</tbody>
</table>
<button type="button" name="addRow" value="addRow" id="addRow" class="btn btn-primary">Add Item</button>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
You can use .on("click", "selector", fuction() {})
to perform what you need, the example below works as requested. You can't bind an event trigger to an element that doesn't exist yet, so you need to bind it to something that does (i.e. the table) and then listen for click
events on the selector .deleteRow
.
Your event isnt triggering because there's no id
assigned to your dynamically created row cell for the delete button. BUT, you shouldn't re-use an id
for multiple elements so I would switch to using a class
as I have below.
Demo
$(document).ready(function() {
$("#addRow").click(function() {
var markup = "<tr><td><input type=\"text\" class=\"form-control\" autocomplete=\"off\" placeholder=\"Serial\" name=\"serial\"></td><td></td><td></td><td></td><td class='deleteRow'><span class=\"glyphicon glyphicon-trash\"></span></td></tr>";
$("#shipmentConsignment").append(markup);
});
// Find and remove selected table rows
$("#shipmentConsignment").on("click", ".deleteRow", function() {
$(this).closest('tr').remove();
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<table id="shipmentConsignment" class="table table-condensed table-striped table-bordered">
<thead>
<th class="text-center" scope="col" width="20%">Serial</th>
<th class="text-center" scope="col" width="15%">ID</th>
<th class="text-center" scope="col" width="15%">Code</th>
<th class="text-center" scope="col" width="45%">Description</th>
<th class="text-center" scope="col" width="5%"></th>
</thead>
<tbody>
<tr>
<td><input type="text" class="form-control" autocomplete="off" placeholder="Serial" name="serial"></td>
<td></td>
<td></td>
<td></td>
<td class="deleteRow"><span class="glyphicon glyphicon-trash"></span></td>
</tr>
</tbody>
</table>
<button type="button" name="addRow" value="addRow" id="addRow" class="btn btn-primary">Add Item</button>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Keep in mind that the id attribute is meant to be unique.
what you can do is delegate the deletion to the table
$(document).ready(function() {
$("#addRow").click(function() {
var markup = "<tr><td><input type=\"text\" class=\"form-control\" autocomplete=\"off\" placeholder=\"Serial\" name=\"serial\"></td><td></td><td></td><td></td><td><span class=\"glyphicon glyphicon-trash\"></span></td></tr>";
$("#shipmentConsignment").append(markup);
});
// only delete row if the glyphicon-trash was clicked
$('#shipmentConsignment').click(function (ev) {
if (ev.target.matches('.glyphicon-trash')) {
$(ev.target).closest('tr').remove();
}
});
});
CodePudding user response:
This is because the initial row is different from the ones being appended. To solve this, use class for deleteRow
instead of id to group all columns to be used in the click handler as shown below:
$(document).ready(function() {
// define markup and append one row
const markup = "<tr><td><input type=\"text\" class=\"form-control\" autocomplete=\"off\" placeholder=\"Serial\" name=\"serial\"></td><td></td><td></td><td></td><td class=\"deleteRow\"><span class=\"glyphicon glyphicon-trash\"></span></td></tr>";
$("#shipmentConsignment").append(markup);
// append markup on #addRow click
$("#addRow").click(function() {
$("#shipmentConsignment").append(markup);
});
// remove closest row to the clicked element with class deleteRow
$(document).on("click", ".deleteRow", function() {
$(this).closest('tr').remove();
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<table id="shipmentConsignment" class="table table-condensed table-striped table-bordered">
<thead>
<th class="text-center" scope="col" width="20%">Serial</th>
<th class="text-center" scope="col" width="15%">ID</th>
<th class="text-center" scope="col" width="15%">Code</th>
<th class="text-center" scope="col" width="45%">Description</th>
<th class="text-center" scope="col" width="5%"></th>
</thead>
<tbody>
</tbody>
</table>
<button type="button" name="addRow" value="addRow" id="addRow" class="btn btn-primary">Add Item</button>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
As you've clearly seen the duplicate and are still stuck, here's what to do and how it works
What to do. Change your structure to use a class instead of an ID because you can't use the same ID over and over. Each must be unique. Note the <td >
below
<tr>
<td><input type="text" class="form-control" autocomplete="off" placeholder="Serial" name="serial"></td>
<td></td>
<td></td>
<td></td>
<td class="deleteRow"><span class="glyphicon glyphicon-trash"></span></td>
</tr>
Then change your ADD function to reflect this
$("#addRow").on('click',function() {
var markup = "<tr><td><input type=\"text\" class=\"form-control\" autocomplete=\"off\" placeholder=\"Serial\" name=\"serial\"></td><td></td><td></td><td></td><td class='deleteRow'><span class=\"glyphicon glyphicon-trash\"></span></td></tr>";
$("#shipmentConsignment").append(markup);
});
Finally, update your listener to be a delegate. This means you attach the listener to a static containing element (one that is not dynamically created) and reference the actual element you want in the delegate. That way any newly added rows will keep their functionality
// Find and remove selected table rows
$("#shipmentConsignment").on('click', '.deleteRow', function() {
$(this).closest('tr').remove();
});
More about jQuerys implementation of event delegation: https://api.jquery.com/on/