MVC5中如何将jQuery获取的表格行数传递至CSHTML的For循环
解决MVC5动态表格行增删与服务器端绑定的问题
嘿,我来帮你搞定这个问题!首先得明确一个关键:服务器端的@for循环是在页面发送到浏览器之前就执行完的,而你的jQuery代码是浏览器加载完页面后才运行的——这俩完全不在一个执行时机上,所以你没法直接把客户端计算的rowCount传给服务器端的循环。不过别慌,我给你一套靠谱的实现方案,既能用glyphicon实现增删行,还能让MVC正确识别并绑定提交的数据:
核心思路
- 用MVC的
EditorTemplate统一渲染表格行,确保表单字段的name属性自动符合MVC集合绑定规则(比如[0].PropertyName格式) - 用jQuery克隆行时,更新新行表单元素的索引,保证绑定正常
- 删除行后重新排序剩余行的索引,避免索引断裂导致绑定失败
具体操作步骤
1. 创建行的EditorTemplate
在Views/Shared/EditorTemplates文件夹下(没有的话手动新建),创建对应你行数据模型的模板文件。假设你的行模型叫RuleItem,就新建RuleItem.cshtml:
@model YourProject.Models.RuleItem <tr> <td> @Html.TextBoxFor(m => m.Property1, new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.Property1) </td> <td> @Html.TextBoxFor(m => m.Property2, new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.Property2) </td> <td> <span class="glyphicon glyphicon-plus text-success" aria-hidden="true" style="cursor:pointer;"></span> <span class="glyphicon glyphicon-remove text-danger" aria-hidden="true" style="cursor:pointer;margin-left:10px;"></span> </td> </tr>
2. 主视图中渲染表格
主视图不再需要@for循环,直接用Html.EditorFor渲染你的集合属性:
@model YourProject.Models.RuleViewModel @{ ViewBag.Title = "Manage Rules"; } <form id="ruleForm" method="post" action="@Url.Action("SaveRules")"> <table id="ruleTable" class="table table-bordered"> <thead> <tr> <th>Property 1</th> <th>Property 2</th> <th>Actions</th> </tr> </thead> <tbody> @Html.EditorFor(m => m.RuleItems) <!-- 如果初始无数据,手动渲染一行空行 --> @if (Model.RuleItems == null || Model.RuleItems.Count == 0) { @Html.EditorFor(m => new RuleItem()) } </tbody> </table> <button type="submit" class="btn btn-primary mt-3">Save Rules</button> </form>
3. 编写jQuery增删行脚本
注意用事件委托绑定动态生成元素的事件,同时处理索引更新逻辑:
$(function () { // 添加行事件 $(document).on('click', '.glyphicon-plus', function () { var $tbody = $('#ruleTable tbody'); // 获取最后一行的索引 var lastRowIndex = parseInt($tbody.find('tr:last').find('input').first().attr('name').match(/\[(\d+)\]/)[1]); // 克隆最后一行 var $newRow = $tbody.find('tr:last').clone(true); // 更新新行所有表单元素的name和id索引 $newRow.find(':input').each(function () { var newName = $(this).attr('name').replace(/\[(\d+)\]/, '[' + (lastRowIndex + 1) + ']'); var newId = $(this).attr('id').replace(/\[(\d+)\]/, '[' + (lastRowIndex + 1) + ']'); $(this).attr({ 'name': newName, 'id': newId }).val(''); // 清空输入值 }); // 将新行添加到表格 $newRow.appendTo($tbody); }); // 删除行事件 $(document).on('click', '.glyphicon-remove', function () { var $tbody = $('#ruleTable tbody'); var $currentRow = $(this).closest('tr'); // 至少保留一行数据 if ($tbody.find('tr').length > 1) { $currentRow.remove(); // 重新排序剩余行的索引,保证绑定正常 $tbody.find('tr').each(function (index) { $(this).find(':input').each(function () { var updatedName = $(this).attr('name').replace(/\[(\d+)\]/, '[' + index + ']'); var updatedId = $(this).attr('id').replace(/\[(\d+)\]/, '[' + index + ']'); $(this).attr({ 'name': updatedName, 'id': updatedId }); }); }); } else { alert('至少要保留一行数据哦!'); } }); });
4. 控制器接收数据
你的ViewModel需要包含List<RuleItem>类型的属性,控制器Action可直接接收:
[HttpPost] public ActionResult SaveRules(RuleViewModel model) { if (ModelState.IsValid) { // 编写你的保存逻辑,比如存入数据库 return RedirectToAction("Index"); } // 验证失败返回视图,保留用户输入 return View(model); }
方案优势说明
之前你想把客户端rowCount传给服务器端@for循环,本质是混淆了服务器端渲染和客户端交互的时机。现在用EditorTemplate生成符合MVC绑定规则的表单元素,动态增删行时只需维护好表单索引,MVC就能自动把所有行数据绑定到集合中,完全不需要依赖服务器端循环渲染动态行!
内容的提问来源于stack exchange,提问作者Prakash
相关产品推荐
相关产品推荐

