You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel视图foreach循环中实现JavaScript批量自动计算租金

解决Laravel Blade多组表单批量计算的问题

问题根源

你大概率是用了唯一ID选择器(比如getElementById或querySelector('#xxx')),但Blade循环生成的多组表单会重复ID,JS只能找到第一个匹配的元素,导致后续组的计算完全触发不了。

解决方案

1. 修正Blade视图:用类名替代重复ID,给每组加统一容器

把原来的id换成类名,同时给每组表单包裹一个容器(比如form-group),方便JS定位当前组的所有元素:

@foreach($items as $index => $item)
<div class="form-group">
    <input type="number" class="total-area" name="total_area[]" value="{{ $item->total_area }}">
    <input type="number" class="price-rate-yr1" name="price_rate_yr1[]" value="{{ $item->price_rate_yr1 }}">
    <input type="number" class="monthly-rent-yr1" name="monthly_rent_yr1[]" readonly>

    <input type="number" class="price-rate-yr2" name="price_rate_yr2[]" value="{{ $item->price_rate_yr2 }}">
    <input type="number" class="monthly-rent-yr2" name="monthly_rent_yr2[]" readonly>

    <input type="number" class="price-rate-yr3" name="price_rate_yr3[]" value="{{ $item->price_rate_yr3 }}">
    <input type="number" class="monthly-rent-yr3" name="monthly_rent_yr3[]" readonly>
</div>
@endforeach

2. 改写JavaScript:基于当前组触发计算

推荐用事件委托(性能更优),也可以直接遍历每组绑定事件,两种方案任选:

方案一:事件委托(推荐)

监听全局输入事件,只处理目标属于计算相关的输入框,再定位到它所在的表单组进行计算:

document.addEventListener('input', function(e) {
    const target = e.target;
    // 只处理我们需要的输入框
    if (!target.classList.contains('total-area') && !target.classList.contains('price-rate-yr1') && !target.classList.contains('price-rate-yr2') && !target.classList.contains('price-rate-yr3')) {
        return;
    }

    // 获取当前输入框所在的表单组
    const formGroup = target.closest('.form-group');
    if (!formGroup) return;

    // 取当前组内的所有值,空值或非数字按0处理
    const totalArea = parseFloat(formGroup.querySelector('.total-area').value) || 0;
    const rateYr1 = parseFloat(formGroup.querySelector('.price-rate-yr1').value) || 0;
    const rateYr2 = parseFloat(formGroup.querySelector('.price-rate-yr2').value) || 0;
    const rateYr3 = parseFloat(formGroup.querySelector('.price-rate-yr3').value) || 0;

    // 计算并赋值,保留两位小数可按需调整
    formGroup.querySelector('.monthly-rent-yr1').value = (totalArea * rateYr1).toFixed(2);
    formGroup.querySelector('.monthly-rent-yr2').value = (totalArea * rateYr2).toFixed(2);
    formGroup.querySelector('.monthly-rent-yr3').value = (totalArea * rateYr3).toFixed(2);
});

方案二:遍历每组绑定独立事件

如果需要更直观的绑定逻辑,可以遍历所有表单组,给组内的输入框单独绑定计算事件:

// 获取所有表单组
const formGroups = document.querySelectorAll('.form-group');

formGroups.forEach(group => {
    // 拿到当前组内的所有输入元素
    const totalAreaInput = group.querySelector('.total-area');
    const rateYr1Input = group.querySelector('.price-rate-yr1');
    const rateYr2Input = group.querySelector('.price-rate-yr2');
    const rateYr3Input = group.querySelector('.price-rate-yr3');
    const rentYr1Input = group.querySelector('.monthly-rent-yr1');
    const rentYr2Input = group.querySelector('.monthly-rent-yr2');
    const rentYr3Input = group.querySelector('.monthly-rent-yr3');

    // 定义计算函数
    const calculate = () => {
        const totalArea = parseFloat(totalAreaInput.value) || 0;
        const rateYr1 = parseFloat(rateYr1Input.value) || 0;
        const rateYr2 = parseFloat(rateYr2Input.value) || 0;
        const rateYr3 = parseFloat(rateYr3Input.value) || 0;

        rentYr1Input.value = (totalArea * rateYr1).toFixed(2);
        rentYr2Input.value = (totalArea * rateYr2).toFixed(2);
        rentYr3Input.value = (totalArea * rateYr3).toFixed(2);
    };

    // 给相关输入框绑定输入事件
    totalAreaInput.addEventListener('input', calculate);
    rateYr1Input.addEventListener('input', calculate);
    rateYr2Input.addEventListener('input', calculate);
    rateYr3Input.addEventListener('input', calculate);

    // 页面加载时先算一次,确保初始值正确
    calculate();
});

关键注意点

  • 永远不要在循环里生成重复ID,用类名替代才是正确做法。
  • 通过closest('.form-group')或遍历组,确保计算只针对当前组的元素,不会干扰其他组。
  • 用parseFloat(xxx.value) || 0处理空输入,避免出现NaN的计算结果。

内容的提问来源于stack exchange,提问作者Najwa Ismail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:13:25