I have created a HTML table where every row retrieves data from an sql database table.
?>
<div class="container">
<h2>Activities</h2>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Date</th>
<th scope="col">Position</th>
<th scope="col">Activity Type</th>
<th scope="col">Edit</th>
</tr>
</thead>
<tbody>
<?php
$incremental=0;
while($selRow=$res_selPostData->fetch_assoc()) {
$incremental +=1;
$filepath='.outputs\' . 'verbale' . $selRow['IDIntervento'] . '.pdf';
?>
<tr>
<td><?php echo $selRow['IDActivity']; ?></td>
<td><?php echo $selRow['DateActivity']; ?></td>
<td><?php echo $selRow['Position']; ?></td>
<td><div id=<?php echo "TypeAct" . $incremental; ?>><?php echo $selRow['Activity_type']; ?></div></td>
<td><div id=<?php echo "button" . $incremental; ?>><span id='edit'>EDIT</span></div></td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
The last column of the HTML table contains for each row a ‘button’ which is connected to the following javascript function.
<script>
window.onload = function() {
var maximum=parseInt(<?php echo $incremental; ?>);
for (let i = 1; i<maximum; i++) {
var makeMod = document.getElementById('TypeAct' + 'i');
var div = document.getElementById('button' + 'i');
div.onclick = function(e) {
makeMod.contentEditable = true;
makeMod.focus();
makeMod.style.backgroundColor = '#E0E0E0';
makeMod.style.border = '1px dotted black';
}
}
}
</script>
I had tried using the script without the for loop with
<td><div id=<?php echo "button"; ?>><span id='edit'>EDIT</span></div></td>
and
var makeMod = document.getElementById('TypeAct')` and `var div = document.getElementById('button')
but in that case the function works only for one row.
Changing ‘i’ to i solved the problem with the ‘button’ but when i click the button in different rows only the activity_type in the last row becomes editable and not the one in the same row as the button; as if the function only acts on the last generated row in the while loop of the table. Can you guess why?
3
Answers
On this line:
the ‘i’ is in quotes, thus not getting the calculated value but literally the letter "i". Instead, try:
and ideally use a hyphen between the word button and the increment variable like:
Im using a sample HTML with sample data I made just to test the code, since PHP can’t be reproduced in here so.
First thing first, replace the string
i
with the variable (which you already did)makeMod = document.getElementById('TypeAct-' + i);
This line of code is inside a loop.
<span id='edit'>EDIT</span>
which means you will have multiple elements with theedit
id. Can’t have that so change it like you did with the other ids. You can concatenate your php variable$incremental
like you did with the others.Change your loop to this
for (let i = 1; i <= maximum; i++) {
if you leave it toi < maximum
then it won’t add the event to your last button.It is much better to use
let
andconst
instead ofvar
now. More info hereUse
addEventListener
instead ofonclick
. Why? read more about it here addEventListener-vs-onclickIt would be better, IMO, to remove the ID attributes entirely if you need to use a numerical suffix to help identify elements and rely on other, more flexible means of identifying DOM elements, such as
querySelector
,querySelectorAll
and other parent/child/sibling type properties & methods. In the above the only use that the PHP variable$incremental
has is as that numeric suffix – it would play no part in whatever actualedit
operation (Form submission/ ajax etc) when the record is to be edited so could be removed. The table is generated with content from a database so you have anIDActivity
which will be useful in an edit operation so assign that as the data-id value!The identifying of
click
events can be done using adelegated event listener
rather than assigning an event listener to eachbutton
.I also added a
blur
event handler to the contentEditable DIV elements that returns them to their normal state when no longer used. Thatblur
handler could be used to fire off the ajax request to edit the record in db.