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

ASP.NET Core 带下拉列表的多行插入无法新增行问题

问题原因

新增行功能失效的核心触发点是JS运行时报错中断,连带还有几个逻辑和语法问题:

  • 下拉框是<select>元素,本身没有type属性,原有代码在遍历输入元素时直接取type属性后调用toLowerCase(),对select元素来说取到的type是undefined,执行方法直接抛类型错误,整个新增行的逻辑直接终止,这就是加了下拉框之后点按钮没反应的直接原因。
  • 动态新增的删除按钮没有用事件委托绑定事件,新增出来的行点删除无响应。
  • 视图里的Razor语法漏写@前缀,Html.BeginForm、AntiForgeryToken、ValidationSummary这些辅助方法会被直接当普通文本输出,表单根本不会正常渲染。
  • 克隆行时没有重置下拉框的选中状态,新增行会直接复制上一行的选中值,不符合初始空选的预期。
  • 行内多个div写了固定id,重复id会导致DOM查询、表单验证出现异常。
修复方案

1. 修正JS新增行逻辑

把原来只处理text输入框的逻辑改成兼容select,加上空值判断避免报错,同时重置下拉框选中状态,把删除按钮的事件改成委托形式:

$(document).ready(function () {
    // 新增行
    $("#addNew").click(function (e) {
        e.preventDefault();
        var $tableBody = $("#dataTable");
        var $trLast = $tableBody.find("tr:has(:input)").last(); // 排除表头行
        var $trNew = $trLast.clone(true);

        // 取当前行索引
        var suffix = $trNew.find(':input:first').attr('name').match(/\d+/)[0];
        var newIndex = parseInt(suffix) + 1;
        $trNew.find("td:last").html('<a href="#" class="remove">Remove</a>');
        
        $.each($trNew.find(':input'), function (i, val) {
            // 更新name属性的索引
            var oldN = $(this).attr('name');
            var newN = oldN.replace('[' + suffix + ']', '[' + newIndex + ']');
            $(this).attr('name', newN);
            // 更新id属性避免重复
            var oldId = $(this).attr('id');
            if(oldId){
                $(this).attr('id', oldId.replace('_' + suffix + '__', '_' + newIndex + '__'));
            }

            // 重置值,兼容text和select
            if ($(this).is('input[type="text"]')) {
                $(this).val('');
            }
            if ($(this).is('select')) {
                $(this).prop('selectedIndex', 0); // 重置为第一个选项,需要空选可以加默认空选项
            }

            // 清除验证错误样式
            $(this).removeClass("input-validation-error");
            $(this).nextAll('.field-validation-error').remove();
        });

        $trLast.after($trNew);

        // 重新绑定表单验证
        var form = $("form")
            .removeData("validator")
            .removeData("unobtrusiveValidation");
        $.validator.unobtrusive.parse(form);
    });

    // 删除行,用事件委托兼容动态新增元素
    $(document).on("click", 'a.remove', function (e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });
});

2. 修正视图Razor语法错误

把漏写的@前缀补上,去掉重复的固定id,下拉框可加默认空选项提升使用体验:

@model List<EFCore.Models.ContactInfoNew>
@{
    ViewBag.Title = "Insert Bulk Data";
}
                    
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json2/20160511/json2.js" integrity="sha512-h3RrO+eudpiPUYFkwORXD2ppuy9jOXQ+MzVEIo7k+OuA7y9Ze5jsQ5WN/ZSgI+ZSIngT6pDSaqpgmnam2HPe1g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div style="width:700px; padding:5px; background-color:white;">
    @* 补@前缀修正Razor语法 *@
    @using (Html.BeginForm("BulkData","Home", FormMethod.Post))
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)
        
        if (ViewBag.Message != null)
        {
            <div style="border:solid 1px green">
                @ViewBag.Message
            </div>
        }
        
        <div><a href="#" id="addNew">Add New</a></div>
        <table id="dataTable" border="0" cellpadding="0" cellspacing="0">
            <tr>
                <th>Contact Name</th>
                <th>Contact No</th>
                <th>Test</th>
                <th></th>
            </tr>
            @if (Model != null && Model.Count > 0)
            {
                int j = 0;
                foreach (var i in Model)
                {
                    <tr style="border:1px solid black">
                       
                        <td>
                            @* 移除重复固定id *@
                            @Html.TextBoxFor(a=>a[j].ContactName)
                        </td>

                        <td>
                            @Html.TextBoxFor(a=>a[j].ContactNo)
                        </td>

                        <td>
                            @* 增加默认空选项 *@
                            @Html.DropDownListFor(a=>a[j].TestId, (IEnumerable<SelectListItem>)ViewBag.New, "--请选择--")
                        </td>

                        <td>
                            @if (j > 0)
                            {
                                <a href="#" class="remove">Remove</a>
                            }
                        </td>
                    </tr>
                    j++;
                }
            }
        </table>
        <input type="submit" value="Save Bulk Data" />
    }
</div>

3. 可选优化

ASP.NET Core的模型绑定默认支持非连续索引,如果删除中间行后担心绑定失败,可以在删除行后重新遍历所有数据行,更新输入框name属性的索引值保持连续,或者为每个条目添加对应索引的隐藏字段即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 09:36:17