You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为表格添加新行并在输入价格后自动计算金额(数量×单价)

实现产品表格自动计算金额并动态添加行的解决方案

我帮你梳理并解决这个问题,原代码存在几个关键问题(比如全局变量导致行数据冲突、添加行逻辑不完整、输入类型错误等),下面是修改后的完整实现和详细解释:

修改后的完整代码

<table id="products_table" class="table table-hover" name="products">
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Quantity</th>
      <th scope="col">Pieces</th>
      <th scope="col">Price</th>
      <th scope="col">Amount</th>
    </tr>
  </thead>
  <tbody>
    <!-- 模板行:隐藏起来作为克隆原型,避免初始显示重复内容 -->
    <tr class="template-row" id="templateRow" style="display:none">
      <td>
        <select style="margin-left:20px" name="product_id">
          <?php while($r = mysqli_fetch_assoc($presult)) { ?>
            <option value="<?php echo $r["id"]?>"><?php echo $r["name"]?></option>
          <?php } ?>
        </select>
      </td>
      <td><input type="number" name="quantity" step="0.01" oninput="calculateAmount(this)"></td>
      <td><input type="number" name="pieces" step="0.01"></td>
      <td><input type="number" name="price" step="0.01" oninput="calculateAmount(this)"></td>
      <td><input type="text" name="amount" readonly></td>
    </tr>
    <!-- 初始显示的第一行产品 -->
    <tr class="product-row">
      <td>
        <select style="margin-left:20px" name="product_id">
          <?php while($r = mysqli_fetch_assoc($presult)) { ?>
            <option value="<?php echo $r["id"]?>"><?php echo $r["name"]?></option>
          <?php } ?>
        </select>
      </td>
      <td><input type="number" name="quantity" step="0.01" oninput="calculateAmount(this)"></td>
      <td><input type="number" name="pieces" step="0.01"></td>
      <td><input type="number" name="price" step="0.01" oninput="calculateAmount(this)"></td>
      <td><input type="text" name="amount" readonly></td>
    </tr>
  </tbody>
</table>

<script>
// 计算当前行的金额,并自动添加新行
function calculateAmount(element) {
  // 获取当前输入框所在的产品行
  const row = element.closest('.product-row');
  if (!row) return;

  // 提取当前行的数量和单价(默认值为0,避免NaN)
  const quantity = parseFloat(row.querySelector('input[name="quantity"]').value) || 0;
  const price = parseFloat(row.querySelector('input[name="price"]').value) || 0;

  // 计算金额并填充到对应输入框,保留两位小数
  const amount = quantity * price;
  row.querySelector('input[name="amount"]').value = amount.toFixed(2);

  // 自动添加新行:仅当当前是最后一行,且数量和单价都有有效值时触发
  const tableBody = document.querySelector('#products_table tbody');
  const lastRow = tableBody.querySelector('.product-row:last-child');
  if (row === lastRow && quantity > 0 && price > 0) {
    addNewRow();
  }
}

// 克隆模板行并添加到表格末尾
function addNewRow() {
  const templateRow = document.querySelector('#templateRow');
  const tableBody = document.querySelector('#products_table tbody');

  // 克隆模板行(true表示克隆所有子元素)
  const newRow = templateRow.cloneNode(true);
  // 移除模板行的ID,避免DOM中出现重复ID
  newRow.removeAttribute('id');
  // 显示新行(模板行默认是隐藏的)
  newRow.style.display = '';
  // 添加产品行类,方便后续关联
  newRow.classList.add('product-row');

  // 清空新行的所有输入框值,避免继承模板行的内容
  const inputs = newRow.querySelectorAll('input');
  inputs.forEach(input => input.value = '');

  // 将新行添加到表格tbody的末尾
  tableBody.appendChild(newRow);
}
</script>

关键改进点说明

  • 修正输入框类型:把原代码的type="float"改为type="number"(HTML中没有float类型的输入框),并添加step="0.01"支持小数输入,提升用户体验。
  • 移除全局变量,实现行独立计算:不再用全局变量存储数量,而是通过element.closest('.product-row')定位当前输入框所在的行,确保每行的数量和价格都是独立计算,不会互相干扰。
  • 自动计算并填充金额:当数量或单价发生变化时,自动计算金额并填充到对应输入框,同时设置金额输入框为readonly,避免用户手动修改,保证数据准确性。
  • 智能添加新行:仅当最后一行的数量和单价都输入有效值时,自动克隆模板行添加到表格末尾,用户无需手动操作即可继续输入下一个产品。
  • 模板行复用:将原模板行隐藏,作为克隆的原型,避免初始页面显示重复的下拉框内容,同时保证新行的结构和初始行完全一致。

内容的提问来源于stack exchange,提问作者Kamal Kannan

火山引擎 最新活动