0

I am struggling with adding a button to a table cell. The button should fire a function by calling its name and sending it two arguments. Can anyone show a simple example. This is what I tried to do but it has two problems: 1) the button appear so small almost invisible. 2) The event never fires (also the function is big and I want it to be called by its name because I want to place its body outside).

var info = [{
  "firstName": "aaa",
  "lastName": "A"
}, {
  "firstName": "bbb",
  "lastName": "B"
}, {
  "firstName": "ccc",
  "lastName": "C"
}];
var table = document.getElementById("table");
var storageLength = info.length;

for (var i = 0; i < info.length; i++) {
  var row = table.insertRow(i + 1);
  var cell1 = row.insertCell(0);
  var cell2 = row.insertCell(1);
  var cell3 = row.insertCell(2);

  cell1.innerHTML = info[i].firstName;
  cell2.innerHTML = info[i].lastName;

var editbtn = document.createElement('button'); 
editbtn.type= "button";
editbtn.className= "editbtn";
editbtn.id= "button-"+(i+1);
editbtn.value= "Edit";
editbtn.onclick = 'editRow(i+1)';
cell3.appendChild(editbtn);                    // Append <button> to <body> 
} //end for

function editRow(rowindex)
{
    console.log("inside editRow "+(rowindex));
}

HTML:

<table id="table" border='1'>
  <tr></tr>
</table>

EDIT: If you can provide me with a solution for using: var editButtonHTML = "

(i + 1) + " onclick='editRow(" + (i + 1) + ")'>";
cell3.innerHTML=editButtonHTML;

That would be better as this method makes the button appear in the normal size. But my only problem is that I'm not getting the function fired. This problem appears in firefox addon using jpm. With innerHTML, the event get fired when I open the page normally in the browser. I suspect that they syntax should be 'onclick=..' with single quotation not double. When I inspect the HTML, it automatically makes the single quotations as doubles even if I use \ to escape them.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user7945230
  • 1,075
  • 2
  • 13
  • 20
  • Try: `editbtn.onclick = editRow.bind(this, i + 1);` – palaѕн May 28 '17 at 11:04
  • Thanks. But, what about the function body? I am trying `function editRow(n) { console.log("inside edit row"+ n); }`. It works but I am not sure if it correc? how to send two arguments and the function body receives one? I just want to make sure that it won't cause me other problems later. – user7945230 May 28 '17 at 11:16

3 Answers3

0

use innerHTML not value

this is solution for button editbtn.innerHTML = "EDIT"; to add click event editbtn.onclick = (function(i){ return function(){ editRow(i+1)}})(i);

We need to bind i value to that onclick function. the above function does that.

var info = [{
  "firstName": "aaa",
  "lastName": "A"
}, {
  "firstName": "bbb",
  "lastName": "B"
}, {
  "firstName": "ccc",
  "lastName": "C"
}];
var table = document.getElementById("table");
var storageLength = info.length;

for (var i = 0; i < info.length; i++) {
  var row = table.insertRow(i + 1);
  var cell1 = row.insertCell(0);
  var cell2 = row.insertCell(1);
  var cell3 = row.insertCell(2);

  cell1.innerHTML = info[i].firstName;
  cell2.innerHTML = info[i].lastName;

var editbtn = document.createElement('button'); 
editbtn.type= "button";
editbtn.className= "editbtn";
editbtn.id= "button-"+(i+1);
editbtn.value= "Edit";
editbtn.innerHTML = "EDIT";
editbtn.onclick = (function(i){ return function(){ editRow(i+1)}})(i);
cell3.appendChild(editbtn);                    // Append <button> to <body>
} //end for

function editRow(rowindex)
{
    console.log("inside editRow "+(rowindex));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table" border='1'>
  <tr></tr>
</table>
Dinesh undefined
  • 5,490
  • 2
  • 19
  • 40
  • But it always print the last i in the loop. E.g. it will always print `inside editRow 4`. But I want it to be depends on which row I press edit. E.g. row 1 should print ``inside editRow 1`, etc. – user7945230 May 28 '17 at 10:49
  • @user7945230 it took me while to fix that. its working now please check – Dinesh undefined May 28 '17 at 11:18
  • Thanks but still one mroe issue. How to move the function body out? I tried: `editbtn.onclick=editRow(i+1). I tried this: `editbtn.onclick = editRow(i+1); function editRow(i+1) { console.log("inside index: "+i+1);`. But did not work. }(i+1);`. But did not work. – user7945230 May 28 '17 at 12:07
0

In order to solve the issue of editRow printing out the correct row number, you need to use some form of closure. (How do JavaScript closures work?)

What's happening now is that the function's parameter is bound to i, which changes value to 4 by the end of the loop, so every function will be passed 4 as a parameter.

A simple edit would be:

editbtn.onclick = (function(index) {
    editRow(index);
})(i);
Gil Browdy
  • 69
  • 5
  • How can I move the function body out? so I just call editbtn.onclick=editRow(i+1). I tried this: `editbtn.onclick = editRow(i+1); function editRow(i+1) { console.log("inside index: "+i+1); }(i+1);`. But did not work. – user7945230 May 28 '17 at 12:06
  • Use the code snippet provided above as is. `editRow` is still defined outside of the `onclick` assignment. – Gil Browdy May 28 '17 at 12:10
  • It did not work at least for firefox addon. But it might work the file opened from a browser. I accepted @Dinesh answer's. It worked with me. – user7945230 May 28 '17 at 12:16
0

If you want to add a edit button to each table cell, you can do something like this

$('.tableCell').each(function() {
  $target = $(this)
  var content = $target.html()
  $button = $('<button>Edit content✏️</button>')
  $target.append($button);
  $button.on('click', function(e){
    e.preventDefault()
    e.stopPropagation()
    doMagic(content)
  })
})
Tin Lek
  • 96
  • 1
  • 4