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

Laravel表单验证失败时恢复jQuery动态添加输入字段的方法

解决Laravel非Ajax表单提交验证错误后动态字段丢失问题

核心思路

利用Laravel的old()函数获取提交的动态字段数据,在页面加载时通过JavaScript重新渲染这些字段,同时同步更新计数器,确保后续添加新字段的序号正确。

步骤1:修改HTML与Blade模板逻辑

在表格tbody中,保留默认第一行的同时,根据old('expense_details')的数据循环生成验证错误前添加的动态行,并填充用户之前输入的值:

<div class="table-responsive-sm">
    <button type="button" id="addRow" class="btn btn-success btn-sm mt-3 mb-2 float-right"><i class="fas fa-plus"></i>
        Add Row</button>
    <table class="table table-bordered align-middle table-hover text-center align-middle detail-table"
        id="Add_Expense_Table_id">
        <thead>
            <tr>
                <th>name</th>
                <th>value</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody id="Add_Expense_Table_id_tbody">
            <!-- 默认第一行 -->
            <tr>
                <td><input type="text" id="name1" class="form-control" name="expense_details[1][name]"
                        value="{{ old('expense_details.1.name') }}"></td>
                <td><input type="number" id="value1" class="form-control" name="expense_details[1][value]"
                        value="{{ old('expense_details.1.value') }}"></td>
                <td><button type="button" onclick="DeleteRow(this);" class="btn btn-danger btn-sm"><i class="fas fa-ban"></i></button></td>
            </tr>

            <!-- 渲染验证错误前添加的动态行 -->
            @if(old('expense_details'))
                @foreach(old('expense_details') as $index => $detail)
                    @if($index > 1) <!-- 跳过默认的第一行 -->
                    <tr>
                        <td><input type="text" id="name{{ $index }}" class="form-control" name="expense_details[{{ $index }}][name]"
                                value="{{ $detail['name'] }}"></td>
                        <td><input type="number" id="value{{ $index }}" class="form-control" name="expense_details[{{ $index }}][value]"
                                value="{{ $detail['value'] }}"></td>
                        <td><button type="button" onclick="DeleteRow(this);" class="btn btn-danger btn-sm"><i class="fas fa-minus"></i></button></td>
                    </tr>
                    @endif
                @endforeach
            @endif
        </tbody>
    </table>
</div>

步骤2:修正JavaScript逻辑

调整计数器初始化逻辑,优先基于old('expense_details')的长度设置初始值,同时修正原代码中value输入框id重复的问题:

<script>
    // 初始化计数器:优先使用old数据的长度,无old数据则用页面现有行数
    let oldExpenses = {!! json_encode(old('expense_details') ?: []) !!};
    let counter = oldExpenses.length > 0 ? oldExpenses.length + 1 : $("#Add_Expense_Table_id_tbody tr").length + 1;

    $("#addRow").on('click', function () {
        let dataToAppend = `
            <tr>
                <td><input type="text" id="name${counter}" class="form-control" name="expense_details[${counter}][name]" value="{{ old('expense_details.${counter}.name') }}"></td>
                <td><input type="number" id="value${counter}" class="form-control" name="expense_details[${counter}][value]" value="{{ old('expense_details.${counter}.value') }}"></td>
                <td><button type="button" onclick="DeleteRow(this);" class="btn btn-danger btn-sm"><i class="fas fa-minus"></i></button></td>
            </tr>
        `;

        $('#Add_Expense_Table_id_tbody').append(dataToAppend);
        counter++;
    });

    function DeleteRow(that) {
        $(that).closest('tr').remove();
        counter--;
        // 可选:若需要字段索引连续,可在此遍历所有行重新设置name属性的索引值
        // Laravel支持非连续索引的数组,若无特殊需求可忽略此步骤
    }
</script>

关键细节说明

  • 计数器同步:通过old('expense_details')的长度初始化计数器,避免新增字段序号与已恢复字段重复。
  • 旧值回填:动态生成的行同样使用old()函数填充用户之前的输入,保证表单数据连贯性。
  • 唯一id修正:将原代码中固定的value1id改为value${counter},避免多个元素id重复导致的DOM问题。

内容的提问来源于stack exchange,提问作者Khayam Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:24:58