I tried to update values in a table using jQuery. I want that when I click ‘update’ it changes the value and returns the form as it was. Also when i click ‘cancel’ it cancels the update. In my example it doesn’t work.
$(document).on('click', '.btn-edit', function(e) {
var name = $(this).parents("tr").attr('data-name');
var email = $(this).parents("tr").attr('data-email');
$(this).parents("tr").find("td:eq(0)").html('<input name="edit_name" value="' + name + '">');
$(this).parents("tr").find("td:eq(1)").html('<input name="edit_email" value="' + email + '">');
$(this).parents("tr").find("td:eq(2)").prepend("<button class='btn btn-info btn-xs btn-update'>Update</button><button class='btn btn-warning btn-xs btn-cancel'>Cancel</button>")
$(this).hide();
});
$(document).on('click', '.btn-update', function(e) {
var name = $(this).parents("tr").attr('data-name');
var email = $(this).parents("tr").attr('data-email');
$(this).parents("tr").find("td:eq(0)").text(name);
$(this).parents("tr").find("td:eq(1)").text(email);
$(this).parents("tr").find(".btn-edit").show();
$(this).parents("tr").find(".btn-update").remove();
$(this).parents("tr").find(".btn-cancel").remove();
});
$(document).on('click', '.btn-cancel', function(e) {
var name = $(this).parents("tr").find("input[name='edit_name']").val();
var email = $(this).parents("tr").find("input[name='edit_email']").val();
$(this).parents("tr").find("td:eq(0)").text(name);
$(this).parents("tr").find("td:eq(1)").text(email);
$(this).parents("tr").attr('data-name', name);
$(this).parents("tr").attr('data-email', email);
$(this).parents("tr").find(".btn-edit").show();
$(this).parents("tr").find(".btn-cancel").remove();
$(this).parents("tr").find(".btn-update").remove();
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<div class="container">
<table class="table table-bordered ">
<thead>
<th>Name</th>
<th>Email</th>
<th width="200px">Action</th>
</thead>
<tbody>
<tr data-name='marzouk najib' data-email='[email protected]'>
<td>marzouk najib</td>
<td>[email protected]</td>
<td><button class='btn btn-info btn-xs btn-edit'>Edit</button></td>
</tr>
</tbody>
</table>
</div>
4
Answers
When creating a normal event listener, it is immediately tied to existing elements on the page. So dynamic elements won’t get the event listener.
You can use delegation to solve the problem for the btn-update event listener use this instead:
You need to use delegated event handlers as you’re dynamically creating and removing the buttons.
In addition your logic is not quite right. You need to update the data attributes on the
tr
when the ‘update’ button is clicked, not the ‘cancel’.The logic can also be improved by caching your selectors in variables instead of recreating them for each method call. In addition you can use
closest()
instead ofparents()
to get the nearest parenttr
element,data()
instead ofattr()
to read data attributes and alsochildren()
instead offind()
to get the childtd
.With that said, try this:
The problem is that you are setting event listeners for btn-cancel and btn-update when they are not existing yet, try to set the events just after create the buttons, or create the buttons and show/hide the cancel/update buttons.
Don’t need to explain myself like the rest have done by using event delegation
on('click','.btn-update', function(e) {
but i can give you some other suggestions:
.html()
they could embed javascript and other html tags by escaping the quotes. (look at how i solved it instead)$(document).on('click'
it’s better to narrow it down to the table, otherwise the event listener will fire internally in jQuery’s core for every click you do outside of the table$(this).parent('tr').find()
this can be cached and reduce the the amount of work needed to query elements if you just cached the tr and used it as a selector container$('.class', tr)
see how i solved it belowbut still this is far away of how i would deal with it, i would separate the logic from js/html