首页 > 解决方案 > 生成的表事件侦听器行不能立即工作

问题描述

我有一张这样的桌子:

在此处输入图像描述

我已向表中的每个文本框添加了一个事件侦听器assetTableEvent()。我的问题是当我向表中添加新行时,我还向它添加了相应的事件侦听器assetTableEvent(),但是在输入值时总值不会弹出,它仅在下一行输入值时显示。

在此处输入图像描述

 function assetTableEvent() {
    let total = 0;

    for (var k = 0; k < document.getElementById("assetTable").rows.length; k++) {
        var a = document.getElementById("v" + k);
        var o = document.getElementById("o" + k);
        var t = document.getElementById("t" + k);

        if (a == null || o == null) {
            continue;
        }

        if (a.value.length > 0 && o.value.length > 0) {
            t.value = Number.parseInt(a.value - o.value);
            total = (Number.parseInt(t.value) + Number.parseInt(total));
            document.getElementById("totalAssets").value = Number.parseInt(total);
        }
    }

}

我什至尝试在每次发生更改时调用assetTableEvent(),但它不起作用。有人可以在 Javascript 中帮助我如何使动态添加的行对应于事件侦听器,如上面的行。

资产表的 HTML:

<div id="calcContainer">

<div id = "headingText" >
Child Maintenance Calculator
</div>

<div id="startPage">

<button id="startBtn">Start</button>
</div>

<div id="asset">
 <table id="assetTable">
     <tr>

    <th>Asset</th>
    <th>Value</th>
    <th>Own</th>
    <th>Total</th>

</tr>
 </table>
 <div id="totalAssetsDiv">
 <Label for ="totalAssets">Total Assets</Label>
 <input type="number" id = "totalAssets" readonly="true">

 <br>
</div>
 <div id ="rowOps">
    <br> <button id="addRow" class = "addDel">Add Row</button>
   <button id="removeRow" class = "addDel1">Delete Row</button><br>
 </div>
</div>

并添加行事件监听器:

   document.getElementById("addRow").addEventListener("click", function () {

    var table = document.getElementById("assetTable");
    var row = table.insertRow();

    for (let j = 0; j < 4; j++) {
        var tb = document.createElement("INPUT");
        var value = "", idNum = "";

        if (j == 0) {
            tb.setAttribute("type", "text");
            tb.value = value;

        }
        else {
            tb.setAttribute("type", "number");
        }


        //Setting textbox id
        switch (j) {
            case 0:
                idNum = "a";
                break;

            case 1:
                idNum = "v";
                break;

            case 2:
                idNum = "o";
                break;

            case 3:
                idNum = "t";
                break;

        }

        tb.id = idNum + (table.rows.length);

        if (tb.id.includes('t')) {
            tb.setAttribute("readOnly", "true");
        }

        tb.classList.add("assetTBox");
        let cell = row.insertCell(j);
        tb.addEventListener("input", assetTableEvent, false);
        cell.appendChild(tb);
     

    }
});

标签: javascriptaddeventlistener

解决方案


尝试使用增量 ID 的工作量大于其价值,尤其是当您开始删除行时。

我建议您改用类并将事件侦听器委托给表本身。当输入事件发生时,您将获得最近的行并查询该行中的元素以获取行总数,然后查询所有行总数以获取主总数

具有功能添加行的基本示例

const table = document.querySelector('#myTable'),
  cloneRow = table.rows[0].cloneNode(true);


table.addEventListener('input',(e) => {
  if (e.target.matches('.qty, .price')) {
    const row = e.target.closest('tr'),
      price = row.querySelector('.price').valueAsNumber || 0,
      qty = row.querySelector('.qty').valueAsNumber || 0;
    
    row.querySelector('.amt').value = qty * price;
    setTotalAmt()
  }

});

document.querySelector('#add-row').addEventListener('click', (e) => {
  table.appendChild(cloneRow.cloneNode(true))
});

function setTotalAmt() {
  const sum = [...table.querySelectorAll('.amt')].reduce((a, el) => a + (+el.value || 0), 0)
  document.querySelector('#total').value = sum;
}
<button id="add-row">
  Add Row
</button>
Total:<input id="total" />
<table id="myTable">
  <tr>
    <td>Qty:
      <input type="number" class="qty" value="0" />
    </td>
    <td>Price:
      <input type="number" class="price" value="0" />
    </td>
    <td>Amt:
      <input class="amt" readonly value="0" />
    </td>
  </tr>
</table>


推荐阅读