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

使用jQuery动态添加INPUT和SELECT字段的问题排查

问题解决:动态添加带SELECT的表格行并正确提交数据

问题根源

  1. 你使用了固定名称的DropDownList("Status", ...),没有像其他表单字段那样采用带索引的强类型命名格式(如a[j].Project),导致克隆后的下拉框名称始终为Status,无法和数组模型绑定,提交时数据无法被后端正确识别。
  2. 隐藏字段赋值时用$("#id")和$("#email")按ID选择元素,但动态生成的行中这些元素ID重复,会导致赋值错误。
  3. 克隆下拉框后未重置选中状态,新增行会继承最后一行的选中值,不符合新增空白行的需求。

解决方案

1. 修改Razor代码,改用强类型DropDownListFor

将固定名称的下拉框替换为强类型绑定的DropDownListFor,确保下拉框的name属性带有索引,和其他字段命名规则一致:

@if (Model != null && Model.Count > 0)
{
    int j = 0;
    foreach (var i in Model)
    {
        <tr style="border:1px solid black">
            <td>@Html.TextBoxFor(a => a[j].Project, new { @required = "required" })</td>
            <td>@Html.TextBoxFor(a => a[j].Task, new { @required = "required" })</td>
            <td></td>
            <!-- 改用DropDownListFor绑定模型的Status属性,自动生成带索引的name -->
            <td>@Html.DropDownListFor(a => a[j].Status, ViewBag.EnumList as SelectList, "请选择状态", new { @required = "required" })</td>
            <td>@Html.TextBoxFor(a => a[j].UserId, new { @class = "id", @type = "hidden" })</td>
            <td>@Html.TextBoxFor(a => a[j].Email, new { @class = "email", @type = "hidden" })</td>
            <td>@Html.TextBoxFor(a => a[j].Date, new { @type = "hidden" })</td>
            <td></td>
            <td>
                @if (j > 0)
                {
                    <!-- 移除重复ID,改用类选择器绑定事件 -->
                    <button class="remove btn btn-warning">Remove</button>
                }
            </td>
        </tr>
        j++;
    }
}

2. 修改jQuery代码,完善克隆逻辑

修复下拉框名称替换、隐藏字段赋值、表单元素状态重置等问题:

$("#addNew").click(function (e) {
    e.preventDefault();
    var $tableBody = $("#dataTable");
    var $trLast = $tableBody.find("tr:last");
    // 从最后一行获取隐藏字段值,避免全局选择冲突
    var email = $trLast.find(".email").val();
    var userId = $trLast.find(".id").val();
    var $trNew = $trLast.clone();

    // 提取当前行的索引后缀
    var suffix = $trNew.find(':input:first').attr('name').match(/\d+/)[0];
    var newSuffix = parseInt(suffix) + 1;

    // 更新移除按钮,去掉重复ID
    $trNew.find("td:last").html('<button class="remove btn btn-warning">Remove</button>');

    // 遍历所有表单元素,修改名称并重置状态
    $trNew.find(':input').each(function () {
        var $this = $(this);
        // 修改name属性的索引值
        var oldName = $this.attr('name');
        var newName = oldName.replace('[' + suffix + ']', '[' + newSuffix + ']');
        $this.attr('name', newName);

        // 移除重复的ID属性
        $this.removeAttr('id');

        // 根据元素类型处理值或状态
        var type = $this.attr('type');
        if (type) {
            switch (type.toLowerCase()) {
                case "text":
                case "hidden":
                    // 隐藏字段赋值对应值,普通文本框清空
                    if ($this.hasClass('id')) {
                        $this.val(userId);
                    } else if ($this.hasClass('email')) {
                        $this.val(email);
                    } else {
                        $this.val('');
                    }
                    break;
            }
        } else if ($this.is('select')) {
            // 重置下拉框为默认选中项
            $this.prop('selectedIndex', 0);
        }

        // 移除验证错误样式
        $this.removeClass("input-validation-error");
    });

    $trLast.after($trNew);

    // 重新解析表单验证规则
    var form = $("form")
        .removeData("validator")
        .removeData("unobtrusiveValidation");
    $.validator.unobtrusive.parse(form);
});

// 用类选择器绑定移除事件,避免ID冲突
$(document).on('click', '.remove', function () {
    $(this).closest('tr').remove();
});

关键修改说明

  • 强类型下拉框绑定:通过DropDownListFor生成带索引的name(如a[1].Status),确保提交时能正确绑定到后端数组模型。
  • 避免重复ID:移除按钮和表单元素不再使用重复ID,改用类选择器操作,避免DOM选择冲突。
  • 精准赋值隐藏字段:从最后一行的元素中获取隐藏字段值,确保每个新增行的隐藏字段值正确。
  • 重置表单状态:清空文本框内容、重置下拉框选中状态,避免克隆后继承旧数据。
  • 重新验证表单:新增行后重新解析验证规则,确保新增的必填字段能被正确校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 06:33:21