通过jQuery追加行生成的主从表单如何实现CRUD(尤其是编辑视图)
同一PHP文件适配新增/编辑表单方案
1. 核心问题梳理
你之前遇到的布局混乱、下拉框无法选中、动态行重复的问题,核心原因有两个:
- JS动态拼接行的时候混入了Blade模板语法
@foreach,这段语法只能在PHP渲染页面阶段执行,JS运行时会被当成普通字符串无法生成有效下拉选项,所以你才被迫换成了输入框 - 新增行和编辑行的生成逻辑拆分,导致DOM结构不一致出现样式错位
2. 实现步骤
2.1 前端预加载产品数据源
在Blade模板的全局脚本区域,把产品列表提前注入为JS全局变量,后续动态生成行的时候直接调用,不需要再写Blade语法:
<script> // 直接把后端的产品数组转成JS全局变量,所有场景通用 const produkList = @json($produk); // 全局记录行索引,避免ID重复 let currentRowIndex = 0; </script>
2.2 封装公共行生成函数
把新增、编辑场景的行生成逻辑抽成公共函数,保证所有行的DOM结构完全一致,同时支持传入编辑数据自动赋值:
/** * 生成明细行 * @param {number} index 行索引 * @param {object} detail 编辑场景的明细数据,新增场景传空对象即可 * @returns jQuery行对象 */ function createDetailRow(index, detail = {}) { // 生成下拉选项 let optionHtml = '<option disabled value="" selected>Select Produk</option>'; produkList.forEach(pro => { optionHtml += `<option value="${pro.id}" data-berat="${pro.berat_maksimal}">${pro.nama}</option>`; }); // 生成整行HTML const rowHtml = ` <tr> <td><input type="text" class="form-control matras" name="addmore[${index}][matras]" id="matras${index}" value="${detail.no_matras || ''}"></td> <td> <select class="form-control nama" name="addmore[${index}][nama]" id="nama${index}" required> ${optionHtml} </select> </td> <td><input type="text" class="form-control berat" name="addmore[${index}][berat]" id="berat${index}" value="${detail.berat || ''}"></td> <td><input type="text" class="form-control qty" name="addmore[${index}][qty]" id="qty${index}" value="${detail.qty || ''}"></td> <td><input type="text" class="form-control subtotal" name="addmore[${index}][subtotal]" id="subtotal${index}" readonly></td> <td><button type="button" class="btn btn-sm btn-danger remove"> -</button></td> </tr> `; const $row = $(rowHtml); // 编辑场景自动选中下拉值 if(detail.id_aluminium_base) { $row.find('.nama').val(detail.id_aluminium_base).change(); } currentRowIndex = index + 1; return $row; }
2.3 调整编辑场景数据渲染逻辑
统一遍历所有明细数据生成行,不需要单独处理第一行:
$.get(url) .done((response) => { // 赋值主表单字段 $('#modal-form [name=nomor]').val(response.produksi.nomor_laporan); $('#modal-form [name=tanggal]').val(response.produksi.tanggal); $('#modal-form [name=jumlah_billet]').val(response.produksi.jumlah_billet); $('#modal-form [name=jumlah_avalan]').val(response.produksi.jumlah_avalan); $('#modal-form [name=mesin]').val(response.produksi.mesin); $('#modal-form [name=shift]').val(response.produksi.shift); $('#modal-form [name=anggota]').val(response.produksi.anggota); $('#modal-form [name=total_produksi]').val(response.produksi.total_produksi); // 清空旧明细 $('#kas_table').empty(); // 遍历所有明细生成行 response.produksidetail.forEach((detail, idx) => { $('#kas_table').append(createDetailRow(idx, detail)); }); })
2.4 模态框重置逻辑优化
不要清空整个模态框的HTML,只重置表单和明细表格即可:
$("#modal-form").on("hidden.bs.modal", function(){ // 重置主表单 this.reset(); // 清空明细 $('#kas_table').empty(); });
2.5 新增场景逻辑调整
点击新增按钮的时候直接生成空行即可,复用同一个生成函数:
// 新增按钮点击事件 $('.add-btn').click(() => { $('#modal-form').modal('show'); // 默认生成一行空明细 $('#kas_table').append(createDetailRow(0)); }); // 动态加行按钮点击事件 $('.add-row-btn').click(() => { $('#kas_table').append(createDetailRow(currentRowIndex)); }); // 动态删除行(用事件委托适配动态生成的行) $('#kas_table').on('click', '.remove', function() { $(this).closest('tr').remove(); });
3. 后端逻辑无需调整
你现有的控制器show方法可以直接复用,不需要做任何修改。
内容的提问来源于stack exchange,提问作者Mulyono T
相关产品推荐
相关产品推荐

