Foreach循环下产品每行单价与数量的总价计算方案咨询
解决多行产品总价计算的方案
核心思路
不用手动维护递增ID,而是利用DOM元素的层级关系,通过输入框定位到所在的表格行,再获取该行内的单价和总价元素——既避免了重复ID的问题,又能灵活处理任意数量的产品行。
修改后的代码实现
1. PHP/HTML部分调整
<?php include 'main.php'; check_loggedin($pdo); $minerals = $pdo->query('SELECT * FROM products WHERE category = "mineral"'); ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,minimum-scale=1"> <title>Test</title> <link href="style.css" rel="stylesheet" type="text/css"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css"> </head> <body class="loggedin"> <?php include 'navigation.php' ;?> <main> <div class="content"> <h2>Caisse</h2> <div class="content-block"> <form action="" method="post" class=""> <div class="table"> <h3>Minérales</h3> <table> <colgroup> <col width="5%"> <col width="35%"> <col width="20%"> <col width="20%"> <col width="20%"> </colgroup> <thead> <tr> <td>QTY</td> <td class="center">Product</td> <td>Unit</td> <td>Price</td> <td>Total</td> </tr> </thead> <tbody> <?php if (!$minerals): ?> <tr> <td colspan="5" style="text-align:center">There are no minerals</td> </tr> <?php endif; ?> <?php foreach ($minerals as $mineral): ?> <tr> <!-- 传入当前input元素到计算函数,用class替代重复id --> <td><input type="number" min="0" step="1" name="qty_mineral[<?=$mineral['id']?>]" oninput="Calcul_total(this)"></td> <td class="center"><?=$mineral['name']?></td> <td><?=$mineral['unit']?></td> <td class="price"><?=$mineral['price']?></td> <td class="total"></td> </tr> <?php endforeach; ?> </tbody> </table> </div> </form> </div> </div> </main> </body> </html>
关键改动说明:
- 移除重复的
id属性,改用class标识可复用的单价、总价元素 - 输入框
name改为数组格式qty_mineral[<?=$mineral['id']?>],提交表单时能区分不同产品的数量 - 输入框类型设为
number并限制范围,提升输入体验 oninput事件传入当前输入框元素this,让JS能精准定位对应行
2. JavaScript部分调整
function Calcul_total(input) { // 定位当前输入框所在的表格行 const row = input.closest('tr'); // 获取该行的单价并转为数字 const price = parseFloat(row.querySelector('.price').textContent); // 获取输入数量,空值或非数字时默认设为0 const qty = parseFloat(input.value) || 0; // 计算总价并保留两位小数,赋值给对应位置 row.querySelector('.total').textContent = (qty * price).toFixed(2); }
逻辑说明:
- 用
closest('tr')快速定位当前行,无需依赖任何ID - 用
querySelector在该行内精准获取单价和总价元素 - 处理空输入或非数字输入的情况,避免出现NaN
toFixed(2)确保总价以标准金额格式显示
额外优化建议
如果需要计算所有产品的总价总和,可以添加以下函数:
function calculateGrandTotal() { let grandTotal = 0; document.querySelectorAll('.total').forEach(el => { grandTotal += parseFloat(el.textContent) || 0; }); // 把总和插入到页面指定位置,比如表格下方的元素 document.getElementById('grand-total').textContent = grandTotal.toFixed(2); }
只需在每个行计算后调用该函数,或者添加一个"计算总计"按钮触发即可。
内容的提问来源于stack exchange,提问作者Pieric
相关产品推荐
相关产品推荐

