I have a table with a column that has 2 buttons, edit and deactivate. Both function perfectly. However, I also have a button outside of the table that adds a row to the table. On all added rows, neither my edit nor deactivate button work at all. How do I fix this?
HTML/PHP:
<table id="html_master">
<thead>
<tr>
<td>ID</td>
<td>Vendor</td>
<td>Buyer ID</td>
<td>POC Name</td>
<td>POC Email</td>
<td>POC Phone</td>
<td>Edit/Delete</td>
</tr>
</thead>
<tbody>
<?php
foreach ($dbh->query($sql) as $rows){
?>
<tr>
<td class="mr_id" contenteditable="false"><?php echo intval ($rows['MR_ID'])?></td>
<td class="mr_name" contenteditable="false"><?php echo $rows['MR_Name']?></td>
<td class="buyer_id" contenteditable="false"><?php echo $rows['Buyer_ID']?></td>
<td class="poc_n" contenteditable="false"><?php echo $rows['MR_POC_N']?></td>
<td class="poc_e" contenteditable="false"><?php echo $rows['MR_POC_E']?></td>
<td class="poc_p" contenteditable="false"><?php echo $rows['MR_POC_P']?></td>
<td><button class="edit" name="edit">Edit</button>
<button class="deactivate" name="deactivate">Deactivate</button></td>
</tr>
<?php
}
?>
</tbody>
<br>
<input type="button" class="add" value="Add Row" onclick="addRow('html_master')">
</table>
JavaScript:
// ----- Deactivate Row -----
$(document).ready(function() {
$('.deactivate').click(function() {
var $this = $(this);
var $tr = $this.closest('tr');
var action = $tr.hasClass('deactivated') ? 'activate' : 'deactivate';
if (confirm('Are you sure you want to ' + action + ' this entry?')) {
$tr.toggleClass('deactivated');
$this.text(function(i, t) {
return t == 'Deactivate' ? 'Activate' : 'Deactivate';
});
}
})
});
// ----- Add Row -----
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var cell1 = row.insertCell(0);
cell1.innerHTML = rowCount;
var cell2 = row.insertCell(1);
var element2 = document.createElement("input");
element2.type = "text";
element2.name = "txtbox[]";
cell2.appendChild(element2);
var cell3 = row.insertCell(2);
var element3 = document.createElement("input");
element3.type = "text";
element3.name = "txtbox[]";
cell3.appendChild(element3);
var cell4 = row.insertCell(3);
var element4 = document.createElement("input");
element4.type = "text";
element4.name = "txtbox[]";
cell4.appendChild(element4);
var cell5 = row.insertCell(4);
var element5 = document.createElement("input");
element5.type = "text";
element5.name = "txtbox[]";
cell5.appendChild(element5);
var cell6 = row.insertCell(5);
var element6 = document.createElement("input");
element6.type = "text";
element6.name = "txtbox[]";
cell6.appendChild(element6);
var cell7 = row.insertCell(6);
var element7 = document.createElement("input");
var element8 = document.createElement("input");
element7.type = "button";
element8.type = "button";
element7.name="edit";
element8.name="deactivate";
element7.value="Edit";
element8.value="Deactivate";
cell7.appendChild(element7);
cell7.appendChild(element8);
}
$(document).ready(function() {
$('.edit').click(function() {
var $this = $(this);
var tds = $this.closest('tr').find('td').not('.mr_id').filter(function() {
return $(this).find('.edit').length === 0;
});
if ($this.html() === 'Edit') {
$this.html('Save');
tds.prop('contenteditable', true);
} else {
var isValid = true;
var errors = '';
$('#myDialogBox').empty();
tds.each(function(){
var type = $(this).attr('class');
var value = $(this).text();
switch(type){
case "buyer_id":
if(!$.isNumeric(value)){
isValid = false;
errors += "Please enter a valid Buyer ID
";
}
break;
case "poc_n":
if(value == value.match(/^[a-zA-Z\s]+$/)){
break;
}
else {
isValid = false;
errors += "Please enter a valid Name
";
}
break;
case "poc_e":
if(value == value.match(/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/)){
break;
}
else {
isValid = false;
errors += "Please enter a valid Email
";
}
break;
case "poc_p":
if(value == value.match('^[0-9 ()+/-]{10,}$')){
break;
}
else {
isValid = false;
errors += "Please enter a valid Phone Number
";
}
break;
}
})
if(isValid){
$this.html('Edit');
tds.prop('contenteditable', false);
}else{
alert(errors);
}
}
});
});
The dynamically added buttons are not binded to anything.
The solution is to make your onload bindings a function that you can call anytime...
function bindDeactivate() {
$('.deactivate').click(function() {
var $this = $(this);
var $tr = $this.closest('tr');
var action = $tr.hasClass('deactivated') ? 'activate' : 'deactivate';
if (confirm('Are you sure you want to ' + action + ' this entry?')) {
$tr.toggleClass('deactivated');
$this.text(function(i, t) {
return t == 'Deactivate' ? 'Activate' : 'Deactivate';
});
}
});
}
Bind the button on load.
$(document).ready(function() {
// Bind the deactivate button click to the function
bindDeactivate();
});
At the end of your add row function, bind the button.
function addRow(tableID) {
// Skipped a couple lines...
cell7.appendChild(element7);
cell7.appendChild(element8);
// Bind this new deactivate button click to the function
bindDeactivate();
}
You will be able to do the same for the edit button...
;)
EDIT
You had another problem.
Your dynamically added button do NOT have the associated classes.
Add this to your function addRow(tableID)
to add a class to the Deactivate button.
var setClass = document.createAttribute("class");
setClass.value = "deactivate";
element8.setAttributeNode(setClass);
Do the same for the edit button.
See my CodePen here.
EDIT
Okay... Another issue you had:
In your initial HTML, the buttons are <button>
tags.
While the dynamically added ones are <input type="button">
This causes $this.text(function(i, t) {
to be not working on the <input type="button">
.
I changed them for <input type="button">
in your HTML.
And changed $this.text(function(i, t) {
for $this.val(function(i, t) {
I also improved the "double click effect" by unbinding before re-bind... At the end of the addRow(tableID)
function.
// Bind this new deactivate button click to the function
$('#html_master').off("click",'.deactivate');
bindDeactivate();
Please, re-check my codePen again
It is now working (only for Deactivate/Activate button)
You can apply the same logic for the Edit button...
;)
bocz you bind event on load so it work for existing data row but newly added row dont have any binding, try below code to bind event.
$(document).on('click','.deactivate',function() {
var $this = $(this);
var $tr = $this.closest('tr');
var action = $tr.hasClass('deactivated') ? 'activate' : 'deactivate';
if (confirm('Are you sure you want to ' + action + ' this entry?')) {
$tr.toggleClass('deactivated');
$this.text(function(i, t) {
return t == 'Deactivate' ? 'Activate' : 'Deactivate';
});
}
});
and for edit
$(document).on('click','.edit',function() {
var $this = $(this);
var tds = $this.closest('tr').find('td').not('.mr_id').filter(function() {
return $(this).find('.edit').length === 0;
});
});
Try to use an id instead of the class like :
<td><button class="edit" id="edit" name="edit">Edit</button>
<button class="deactivate" id="deactivate" name="deactivate">Deactivate</button></td>
And in the jQuery, replace the ".edit" by "#edit" and ".deactivate" by "#deactivate".
use code
$(document).on('click','.deactivate',function() {
var $this = $(this);
var $tr = $this.closest('tr');
var action = $tr.hasClass('deactivated') ? 'activate' : 'deactivate';
if (confirm('Are you sure you want to ' + action + ' this entry?')) {
$tr.toggleClass('deactivated');
$this.text(function(i, t) {
return t == 'Deactivate' ? 'Activate' : 'Deactivate';
});
}
});
$(document).on('click','.edit',function() {
var $this = $(this);
var tds = $this.closest('tr').find('td').not('.mr_id').filter(function() {
return $(this).find('.edit').length === 0;
});
if ($this.html() === 'Edit') {
$this.html('Save');
tds.prop('contenteditable', true);
} else {
var isValid = true;
var errors = '';
$('#myDialogBox').empty();
tds.each(function(){
var type = $(this).attr('class');
var value = $(this).text();
switch(type){
case "buyer_id":
if(!$.isNumeric(value)){
isValid = false;
errors += "Please enter a valid Buyer ID
";
}
break;
case "poc_n":
if(value == value.match(/^[a-zA-Z\s]+$/)){
break;
}
else {
isValid = false;
errors += "Please enter a valid Name
";
}
break;
case "poc_e":
if(value == value.match(/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/)){
break;
}
else {
isValid = false;
errors += "Please enter a valid Email
";
}
break;
case "poc_p":
if(value == value.match('^[0-9 ()+/-]{10,}$')){
break;
}
else {
isValid = false;
errors += "Please enter a valid Phone Number
";
}
break;
}
})
if(isValid){
$this.html('Edit');
tds.prop('contenteditable', false);
}else{
alert(errors);
}
}
});
The Main reason why the newly added Rows do not respond to the
edit
anddeactivate
Methods is because they were dynamically created and thus were not bound to those initially declaredonclick
Events as the others. You may have to simply attach those events after creating the rows. The code snippet below attempts to illustrate how.
Note:
The snippet below combines all your Javascript code under the JQueryready
Method since there would be no need to have separateready
Methods in one Script. Secondly, to create the new Row, Jquery (rather than Raw Javascript was used). Just for simplicity.
HTML
<table id="html_master">
<thead>
<tr>
<td>ID</td>
<td>Vendor</td>
<td>Buyer ID</td>
<td>POC Name</td>
<td>POC Email</td>
<td>POC Phone</td>
<td>Edit/Delete</td>
</tr>
</thead>
<tbody>
<?php
foreach ($dbh->query($sql) as $rows){
?>
<tr>
<td class="mr_id" contenteditable="false"><?php echo intval ($rows['MR_ID'])?></td>
<td class="mr_name" contenteditable="false"><?php echo $rows['MR_Name']?></td>
<td class="buyer_id" contenteditable="false"><?php echo $rows['Buyer_ID']?></td>
<td class="poc_n" contenteditable="false"><?php echo $rows['MR_POC_N']?></td>
<td class="poc_e" contenteditable="false"><?php echo $rows['MR_POC_E']?></td>
<td class="poc_p" contenteditable="false"><?php echo $rows['MR_POC_P']?></td>
<td><button class="edit" name="edit">Edit</button>
<button class="deactivate" name="deactivate">Deactivate</button></td>
</tr>
<?php
}
?>
</tbody>
</table>
<div class="add-button-wrapper">
<input type="button" class="add" value="Add Row" id="rowAdder">
</div>
JAVASCRIPT: JQUERY
<script type="text/javascript">
$(document).ready(function() {
var rowAdder = $("#rowAdder");
var editButton = $(".edit");
var deActivator = $('.deactivate');
/* EVENT BINDINGS & HANDLING*/
// BIND THE CLICK ACTION TO DEACTIVATION HANDLER
deActivator.click(deactivate);
// BIND THE CLICK EVENT TO THE EDITING HANDLER:
editButton.click(handleEdit);
// BIND THE CLICK ACTION TO THE NEW-ROW PROCESSING HANDLER:
rowAdder.click(addRow);
/* CALL-BACK FUNCTIONS:*/
// HANDLE THE EDITING
function handleEdit(evt) {
var $this = $(this);
var tds = $this.closest('tr').find('td').not('.mr_id').filter(function() {
return $(this).find('.edit').length === 0;
});
if ($this.html() === 'Edit') {
$this.html('Save');
tds.prop('contenteditable', true);
} else {
var isValid = true;
var errors = '';
$('#myDialogBox').empty();
tds.each(function(){
var type = $(this).attr('class');
var value = $(this).text();
switch(type){
case "buyer_id":
if(!$.isNumeric(value)){
isValid = false;
errors += "Please enter a valid Buyer ID
";
}
break;
case "poc_n":
if(value == value.match(/^[a-zA-Z\s]+$/)){
break;
}
else {
isValid = false;
errors += "Please enter a valid Name
";
}
break;
case "poc_e":
if(value == value.match(/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/)){
break;
}
else {
isValid = false;
errors += "Please enter a valid Email
";
}
break;
case "poc_p":
if(value == value.match('^[0-9 ()+/-]{10,}$')){
break;
}
else {
isValid = false;
errors += "Please enter a valid Phone Number
";
}
break;
}
})
if(isValid){
$this.html('Edit');
tds.prop('contenteditable', false);
}else{
alert(errors);
}
}
}
// HANDLE DEACTIVATION
function deactivate(evt) {
var $this = $(this);
var $tr = $this.closest('tr');
var action = $tr.hasClass('deactivated') ? 'activate' : 'deactivate';
if (confirm('Are you sure you want to ' + action + ' this entry?')) {
$tr.toggleClass('deactivated');
$this.text(function(i, t) {
return t == 'Deactivate' ? 'Activate' : 'Deactivate';
});
}
}
// ADD NEW ROW
function addRow(evt) {
var table = $("#html_master");
var rows = table.children("tr");
var rowCount = rows.length;
var row = table.insertRow(rowCount);
// SIMPLY CREATE A NEW ROW OBJECT AND APPEND IT TO THE rows VARIABLE.
var newRow = "<tr>";
newRow += "<td class='mr_id' contenteditable='false'>" + rowCount + "</td>";
newRow += "<td class='buyer_id' contenteditable='false'><input type='text' name='txtbox[]' />" + "</td>";
newRow += "<td class='poc_n' contenteditable='false'><input type='text' name='txtbox[]' />" + "</td>";
newRow += "<td class='poc_e' contenteditable='false'><input type='text' name='txtbox[]' />" + "</td>";
newRow += "<td class='poc_p' contenteditable='false'><input type='text' name='txtbox[]' />" + "</td>";
newRow += "<td class='mr_id' contenteditable='false'><input type='text' name='txtbox[]' />" + "</td>";
newRow += "<td class='mr_id' contenteditable='false'>";
newRow += "<button class='edit' name='edit'>Edit</button>";
newRow += "<button class='deactivate' name='deactivate'>Deactivate</button>";
newRow += "</td>";
newRow += "</tr>";
// APPEND THE NEW ROW...
table.append(newRow);
// RE-BIND THE EVENTS ON THE BUTTONS SINCE THESE WERE DYNAMICALLY CREATED
// BIND THE CLICK ACTION TO DEACTIVATION HANDLER
table.find("deactivate").click(deactivate);
// BIND THE CLICK EVENT TO THE EDITING HANDLER:
table.find("edit").click(handleEdit);
}
});
</script>