
本文详解如何在 asp.net core 6 中通过 javascript 动态增删表格行,并自动重索引 input 的 name 属性,确保提交时模型绑定不因行删除顺序错乱而失效。
本文详解如何在 asp.net core 6 中通过 javascript 动态增删表格行,并自动重索引 input 的 name 属性,确保提交时模型绑定不因行删除顺序错乱而失效。
在 ASP.NET Core 中使用模型绑定(Model Binding)接收集合数据(如 List
✅ 正确做法:删除后立即重索引所有行
原始代码中 counter-- 仅减少计数器,但未修复已存在行的索引,因此破坏了绑定契约。解决方案是在每次删除后,遍历剩余
推荐实现(原生 JavaScript 版)
function removeCurrentRow() {
const table = document.getElementById('grid2');
// 为每行“删除按钮”绑定事件(推荐委托,避免重复绑定)
table.addEventListener('click', function (e) {
if (e.target && e.target.classList.contains('remove-row')) {
const row = e.target.closest('tr');
row.remove();
reorderRows(); // 关键:删除后立即重索引
}
});
}
function reorderRows() {
const table = document.getElementById('grid2');
const rows = table.querySelectorAll('tbody tr'); // 仅处理 tbody 内的行
rows.forEach((row, index) => {
const inputs = row.querySelectorAll('input');
// 按列顺序映射:ItemNumber → Description → Amount → UnitCost
if (inputs.length >= 4) {
inputs[0].name = `POMaterials[${index}].ItemNumber`;
inputs[0].id = `POMaterials[${index}].ItemNumber`;
inputs[1].name = `POMaterials[${index}].Description`;
inputs[1].id = `POMaterials[${index}].Description`;
inputs[2].name = `POMaterials[${index}].Amount`;
inputs[2].id = `POMaterials[${index}].Amount`;
inputs[3].name = `POMaterials[${index}].UnitCost`;
inputs[3].id = `POMaterials[${index}].UnitCost`;
}
});
}
? 关键改进点:
- 使用事件委托(table.addEventListener)替代循环绑定,避免多次调用 addRow() 导致重复监听;
- 删除操作后调用 reorderRows(),按 rows 当前 DOM 顺序(即 [0], [1], [2]...)重写所有 input 的 name;
- querySelectorAll('tbody tr') 确保只处理数据行,跳过表头。
jQuery 简化版(如项目已引入 jQuery)
function removeCurrentRow() {
$('#grid2').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 (colIndex) {
const propName = ['ItemNumber', 'Description', 'Amount', 'UnitCost'][colIndex];
if (propName) {
$(this).attr({
'name': `POMaterials[${rowIndex}].${propName}`,
'id': `POMaterials[${rowIndex}].${propName}`
});
}
});
});
}
⚠️ 注意事项与最佳实践
-
HTML 结构适配:确保删除按钮带有统一 class(如 class="remove-row"),便于事件委托精准捕获:
<button type="button" class="btn btn-sm remove-row" title="Remove Entry"> <span class="k-icon k-i-minus"></span> </button> 避免 counter 依赖索引:counter 仅用于新增行初始编号,不应参与绑定逻辑;重索引完全由 DOM 当前顺序驱动,彻底解耦。
验证与调试技巧:提交前可在浏览器控制台运行 $$('input[name^="POMaterials"]').map(i => i.name) 查看实际生成的 name 列表,确认是否连续有序。
服务端健壮性:即使前端异常,也建议在控制器中对 model.POMaterials 执行空值/长度校验,避免 NullReferenceException。
通过以上方案,无论用户从顶部、中部或底部删除任意行,表单提交时 POMaterials 集合均能被 ASP.NET Core 模型绑定器完整、准确地解析,真正实现动态表格与强类型模型的无缝协同。











