
本文详解如何在 ASP.NET Core 6 中通过 JavaScript 动态增删表格行,并自动重索引 input 的 name 属性,确保提交时模型绑定不因删除中间行而失效。
本文详解如何在 asp.net core 6 中通过 javascript 动态增删表格行,并自动重索引 input 的 `name` 属性,确保提交时模型绑定不因删除中间行而失效。
在使用 ASP.NET Core MVC 模型绑定处理集合(如 List
✅ 正确方案:删除后立即重索引所有行
推荐使用 jQuery + 语义化事件委托 方式实现健壮的动态表格管理(需引入 jQuery):
<!-- 确保页面已引用 jQuery --> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
// 全局计数器(仅用于新增行初始索引)
let counter = 0;
function addRow() {
const tableBody = $('#grid2 tbody');
const newRow = `
<tr>
<td><input type="text" name="POMaterials[${counter}].ItemNumber" id="POMaterials_${counter}_ItemNumber" required></td>
<td><input type="text" name="POMaterials[${counter}].Description" id="POMaterials_${counter}_Description" required></td>
<td><input type="text" name="POMaterials[${counter}].Amount" class="andi" required></td>
<td><input type="text" name="POMaterials[${counter}].UnitCost" class="andi" required></td>
<td>
<button type="button" class="btn btn-sm btn-danger remove-row" title="Remove Entry">
<span class="k-icon k-i-minus"></span>
</button>
</td>
</tr>`;
tableBody.append(newRow);
counter++;
}
// 使用事件委托绑定删除按钮(避免重复绑定)
$(document).on('click', '.remove-row', function () {
$(this).closest('tr').remove();
reindexRows(); // 关键:删除后立即重索引
});
function reindexRows() {
$('#grid2 tbody tr').each(function (rowIndex) {
const $row = $(this);
$row.find('input').each(function (inputIndex) {
const $input = $(this);
let newId, newName;
switch (inputIndex) {
case 0:
newName = `POMaterials[${rowIndex}].ItemNumber`;
newId = `POMaterials_${rowIndex}_ItemNumber`;
break;
case 1:
newName = `POMaterials[${rowIndex}].Description`;
newId = `POMaterials_${rowIndex}_Description`;
break;
case 2:
newName = `POMaterials[${rowIndex}].Amount`;
newId = `POMaterials_${rowIndex}_Amount`;
break;
case 3:
newName = `POMaterials[${rowIndex}].UnitCost`;
newId = `POMaterials_${rowIndex}_UnitCost`;
break;
default:
return;
}
$input.attr('name', newName);
$input.attr('id', newId);
});
});
}
? 关键设计说明:
Giga Coding Agent下载一款AI工具,主要用于通过后台进程运行 Codex CLI、Claude Code、OpenCode 或 Pi Coding Agent,实现程序化控制,适合需要提升相关任务效率的用户。
- 使用 $(document).on('click', '.remove-row', ...) 实现事件委托,避免多次调用 addRow() 导致重复绑定;
- reindexRows() 遍历当前所有
,按实际 DOM 顺序(rowIndex 从 0 开始)重新设置每个 的 name 和 id,彻底消除索引空洞; - id 同步更新为符合 ASP.NET Core 的默认客户端验证 ID 规范(如 POMaterials_0_ItemNumber),保障前端验证正常工作。
⚠️ 注意事项与最佳实践
- 不要手动维护 counter 用于索引逻辑:counter 仅用于新增时生成初始唯一值;真实绑定索引应始终由 reindexRows() 动态计算。
- 禁用原生 onclick 内联脚本:原始代码中 onClick="removeCurrentRow()" 会因 DOM 变化导致事件绑定失效或重复执行,务必改用事件委托。
- 服务端验证不可省略:即使前端重索引正确,仍需在 Controller Action 中检查 ModelState.IsValid,并处理空/无效数据。
- 考虑使用 Tag Helpers 或 View Components:对于复杂表格场景,可封装为可复用组件,进一步提升可维护性。
✅ 验证效果
提交表单后,在控制器中接收模型:
[HttpPost] public IActionResult Create(PurchaseOrderViewModel model) { if (ModelState.IsValid) { // model.POMaterials 将准确包含所有已填写的行(索引连续) _context.PurchaseOrders.Add(model); _context.SaveChanges(); return RedirectToAction("Index"); } return View(model); }只要前端 name 属性连续且格式正确,ASP.NET Core 模型绑定引擎即可自动映射为 List
,无需额外配置。 通过上述方案,无论用户删除第 1 行、中间行还是最后一行,提交数据均能完整、准确地抵达服务端,彻底解决动态表格模型绑定断裂问题。











