JavaScript计算函数在循环生成的表格行中仅第一行生效
解决PHP循环生成表格行中总价计算仅第一行生效的问题
这问题我见得挺多的,核心原因很明确:你在循环里给所有行的输入框都用了相同的id属性,而document.getElementById()只会返回页面中第一个匹配该id的元素。所以不管你在第几行输入,代码永远只会拿第一行的unit_rate、quantity和total_price来计算,后续行自然就没反应了。
下面给你两个可行的解决方案,按需选择:
方案一:给元素添加唯一标识(基于循环计数器)
先修改你的PHP代码,给每个输入框的id和name加上循环计数器后缀,同时把onKeyUp的调用改成传递当前元素的引用,这样能精准定位到触发事件的行:
<?php $counter = 0; foreach($db->getRecordSet($sqlTrRecord) as $row){$counter += 1; ?> <tr class="banktblhd"> <td width="5"><?php echo($counter); ?></td> <td class="w10"><input type="text" name="item_code_<?php echo $counter; ?>" id="item_code_<?php echo $counter; ?>" class="form-control" value="<?php echo($row['item_code']); ?>" readonly /></td> <td class="w20"><input type="text" class="form-control" name="item_name_<?php echo $counter; ?>" id="item_name_<?php echo $counter; ?>" value="<?php echo($row['item_name']); ?>" readonly /></td> <td class="w10"><input type="text" class="form-control" name="description_<?php echo $counter; ?>" id="description_<?php echo $counter; ?>" value="<?php echo($row['description']); ?>" readonly /></td> <td class="w10"><input type="text" class="form-control" name="availableQty_<?php echo $counter; ?>" id="availableQty_<?php echo $counter; ?>" value="<?php echo($row['quantity']); ?>" readonly /></td> <td class="w10"><input type="text" class="form-control" name="unit_rate_<?php echo $counter; ?>" id="unit_rate_<?php echo $counter; ?>" onKeyUp="total(this)" value="<?php echo($row['unit_rate']); ?>" readonly /></td> <td class="w10"><input type="number" class="form-control" name="quantity_<?php echo $counter; ?>" id="quantity_<?php echo $counter; ?>" onKeyUp="total(this)" autocomplete="off" /></td> <td class="w10"><input type="text" class="form-control" name="total_price_<?php echo $counter; ?>" id="total_price_<?php echo $counter; ?>" value="" /></td> </tr> <?php } ?>
然后修改total函数,通过传入的元素找到它所在的表格行,再在该行内查找对应的输入框:
function total(element) { // 定位当前输入框所在的表格行 const currentRow = element.closest('tr'); // 获取当前行的计数器值 const rowNum = currentRow.querySelector('td:first-child').textContent; // 在当前行内找到对应的单价、数量、总价输入框 const unitRateInput = currentRow.querySelector(`#unit_rate_${rowNum}`); const quantityInput = currentRow.querySelector(`#quantity_${rowNum}`); const totalPriceInput = currentRow.querySelector(`#total_price_${rowNum}`); // 处理空值或非数字的情况,避免出现NaN const unitRate = parseFloat(unitRateInput.value) || 0; const quantity = parseFloat(quantityInput.value) || 0; // 计算并赋值总价,可根据需求保留小数位数 totalPriceInput.value = (unitRate * quantity).toFixed(2); }
方案二:使用class定位(更简洁,推荐)
如果不想处理带后缀的id,可以给需要计算的输入框加上专属class,同时把name改成数组形式(方便后续表单提交批量获取数据):
<?php $counter = 0; foreach($db->getRecordSet($sqlTrRecord) as $row){$counter += 1; ?> <tr class="banktblhd"> <td width="5"><?php echo($counter); ?></td> <td class="w10"><input type="text" name="item_code[]" class="form-control" value="<?php echo($row['item_code']); ?>" readonly /></td> <td class="w20"><input type="text" class="form-control" name="item_name[]" value="<?php echo($row['item_name']); ?>" readonly /></td> <td class="w10"><input type="text" class="form-control" name="description[]" value="<?php echo($row['description']); ?>" readonly /></td> <td class="w10"><input type="text" class="form-control" name="availableQty[]" value="<?php echo($row['quantity']); ?>" readonly /></td> <td class="w10"><input type="text" class="form-control unit-rate" name="unit_rate[]" onKeyUp="total(this)" value="<?php echo($row['unit_rate']); ?>" readonly /></td> <td class="w10"><input type="number" class="form-control quantity" name="quantity[]" onKeyUp="total(this)" autocomplete="off" /></td> <td class="w10"><input type="text" class="form-control total-price" name="total_price[]" value="" /></td> </tr> <?php } ?>
对应的total函数会更简洁,完全依赖class定位当前行的元素:
function total(element) { const currentRow = element.closest('tr'); const unitRate = parseFloat(currentRow.querySelector('.unit-rate').value) || 0; const quantity = parseFloat(currentRow.querySelector('.quantity').value) || 0; currentRow.querySelector('.total-price').value = (unitRate * quantity).toFixed(2); }
这个方案的优势在于代码更干净,后续表单提交时,后端可以直接通过$_POST['unit_rate']这种数组形式获取所有行的数据,不用再逐个处理带后缀的字段名。
内容的提问来源于stack exchange,提问作者Sikandar Khan
相关产品推荐
相关产品推荐

