【问题标题】:How to know that which button is clicked, if buttons are added dynamically using javascript?如果使用javascript动态添加按钮,如何知道单击了哪个按钮?
【发布时间】:2019-01-17 09:45:47
【问题描述】:

我不知道如何解决这个问题,如果有人知道如何解决,请告诉我。如果需要,我会亲自发送代码以找出错误。

有两个容器:左和右。在左侧,我从文本框和单选按钮(活动/非活动)中获取标题、描述和状态(活动/非活动)的值。然后在按下提交按钮后,所有值都填充到右侧容器表中,每次单击提交按钮后附加编辑和删除按钮。我想删除单击删除按钮的特定行。但是我不知道如何访问该按钮,而 onclick 功能(doDelete())在所有按钮中都是相同的。

function fillData() {
  var table = document.getElementById("myTable");
  var counter = table.querySelectorAll('tr').length;
  var key = counter;
  var row = table.insertRow(counter);
  row.id = "row-" + key;

  var titleCell = row.insertCell(0);
  var descCell = row.insertCell(1);
  var statusCell = row.insertCell(2);
  var actionCell = row.insertCell(3);

  var editButton = document.createElement("button");
  editButton.innerText = "Edit";
  editButton.id = "edit-" + key;
  editButton.setAttribute("onclick", "doEdit()");

  var delButton = document.createElement("button");
  delButton.innerText = "Delete";
  delButton.id = "delete-" + key;
  delButton.setAttribute("onclick", "doDelete()");

  titleCell.innerHTML = document.getElementById("panel-title").value;
  descCell.innerHTML = document.getElementById("panel-description").value;
  statusCell.innerHTML = (function () {
    var radios = document.getElementsByName("status");
    for (i = 0, len = radios.length; i < len; i++) {
      if (radios[i].checked) {
        return radios[i].value;
      }
    }
  }());

  actionCell.appendChild(editButton);
  actionCell.appendChild(delButton);

  var delBtnArr = document.querySelectorAll('input[type="button"]');
  console.log(delBtnArr);
}

实际结果:按下删除按钮后,整行都被删除。 预期结果:按下删除按钮后,单击按钮的特定行将被删除。

【问题讨论】:

  • 传递给您的删除和编辑方法this.id。在您的特定函数中遍历 dom 树以到达合适的表行。
  • 请出示删除行的代码。
  • 实际上我对如何访问该元素感到困惑,所以没有用 doDelete() 函数编写代码
  • 请给我您的电子邮件 ID,以便我可以与您分享我的代码

标签: javascript html


【解决方案1】:

Javascript 还将关联事件作为参数发送,通过这种方式,您可以使用事件实用程序获取 id。您可以获得点击的按钮 ID,如下所示。通过获取该 id,我认为您还可以获得相关的行。之后,您可以删除该行。

doDelete(event){
 let clickedButtonId = e.target.id;
 //get row id. I think you can get it.
 document.removeElement(rowId);
}

【讨论】:

  • 好的,我会试试的。如果再次出现问题,我会联系您
  • @Champ 你试过了吗?
【解决方案2】:

Event Delegation

将祖先绑定/注册到事件

动态添加的标签不能绑定到事件处理程序/侦听器,只有自页面加载后就存在的标签才能绑定。因此,对于多个动态添加的标签(例如按钮),您必须找到它们都共享不常见的祖先标签并将其绑定到您需要侦听的任何事件。对于您的按钮,它可以是最接近的祖先 table*(推荐)到最远的 window

// On-event property. ALWAYS PASS THE EVENT OBJECT 
table.onclick = function(event) {...

// Event Listener. Abbreviating the [Event Object][2] is OK, but you must be consistent.
table.addEventListener('click', function(e) {...

不要使用事件属性 &lt;button onclick="func()"...

技术上最接近的祖先是tbody,即使你没有将它添加到表中,浏览器也会默认添加它。


使用Event.targetEvent.currentTarget 属性

请记住传递事件对象,因为您需要它来...

  • ...使用event.target 属性找出您实际单击的按钮。

  • ...获取对具有event.currentTarget 属性的表的引用。

  • ...可能会阻止默认行为,例如使用event.preventDefault() 方法阻止表单提交到服务器。

查看演示,它将有关于事件处理程序的具体细节。


演示

demo中评论的详细信息

var table = document.querySelector("table");

document.forms[0].onsubmit = fillData;

/*
This onevent property handler has two functions note it is bound 
to the table NOT the buttons.
There's two conditionals and they only focus on classNames of 
either .del or .edit. Once it's determined if the clicked tag has
one of these classes then the appropriate function is called.
If neither class was clicked there's no opportunity for anything
else to act on the click because both conditionals end with 
return false thereby terminating the event handler.
*/
table.onclick = function(e) {
  if (e.target.className === 'del') {
    delRow(e);
    return false;
  }
  if (e.target.className === 'edit') {
    editRow(e);
    return false;
  }
};

function fillData(e) {
  var ui = e.target.elements;
  e.preventDefault();
  var idx = table.rows.length;
  var row = table.insertRow();
  row.id = 'r-' + idx;

  var cell1 = row.insertCell(0);
  var data1 = ui.title.value;
  cell1.textContent = data1;

  var cell2 = row.insertCell(1);
  var data2 = ui.desc.value;
  cell2.textContent = data2;

  var cell3 = row.insertCell(2);
  var data3 = ui.chk.checked ? 'Active' : 'Inactive';
  cell3.textContent = data3;

  var cell4 = row.insertCell(3);
  var btns = `
  <button class='edit'>&#128221;</button>
  <button class='del'>&#10060;</button>`;
  cell4.innerHTML = btns;
}

/*
Reference the .closest() row from clicked button
Get that row's id and split() it at the dash and pop() the number.
Then get a reference to the bound ancestor (table) and deleteRow() with the new number you just got.
*/
function delRow(e) {
  var row = e.target.closest('tr');
  var idx = row.id.split('-').pop();
  e.currentTarget.deleteRow(idx);
}

/*
Same as before get the index number from the closest row's id.
Reference the table and use the .rows property and number.
This reference will now allow you to use the .cells property.
Use the .cells property to toggle the contenteditable attribute
on the first three cells.
*/
function editRow(e) {
  var row = e.target.closest('tr');
  var idx = row.id.split('-').pop();
  var R = e.currentTarget.rows[idx];
  for (let c = 0; c < 3; c++) {
    var cell = R.cells[c];
    if (cell.hasAttribute('contenteditable')) {
      cell.removeAttribute('contenteditable');
    } else {
      cell.setAttribute('contenteditable', true);
    }
  }
}
body {
  font: 400 16px/25px Consolas;
  display: flex;
  justify-content: space-between;
}

fieldset {
  width: fit-content
}

input,
label,
textarea {
  font: inherit
}

input,
label,
button {
  display: inline-block;
  height: 25px;
}

#title {
  width: 27.5ch;
}

#chk {
  display: none;
}

#chk+label::after {
  content: '\2610';
  font-size: 20px;
  vertical-align: middle;
}

#chk:checked+label::after {
  content: '\2611';
}

[type='reset'] {
  margin-left: 5%
}

td {
  min-width: 60px;
  border-bottom: 1px solid #000;
  height: 25px;
}

tr td:last-child {
  border-bottom-color: transparent;
}

button {
  width: 35px;
  text-align: center;
}
<form id='data'>
  <fieldset>
    <legend>Enter Data</legend>
    <input id='title' type='text' placeholder='Title'><br>
    <textarea id='desc' rows='3' cols='25' placeholder='Description'></textarea><br>
    <input id='chk' type='checkbox'>
    <label for='chk'>Active </label>
    <input type='reset'>
    <input type='submit'>
  </fieldset>
</form>

<hr>

<table></table>

【讨论】:

    猜你喜欢
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    相关资源
    最近更新 更多