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

如何为MVC中多下拉列表绑定带唯一字段ID的onchange事件

MVC多行表单下拉框联动问题解决

我是MVC新手,现有一个包含多行的对话框,每行都有两个DropDownList。第i行的PropertyOne下拉框用于为字段ID为i的项设置PropertyOne属性,因此我希望在onchange事件中获取该字段ID,以便明确要为哪个字段设置PropertyOne。同时,PropertyOne的选择会影响PropertyTwo下拉框的选项。我尝试了一段JavaScript代码但未生效,请问该如何实现?


相关核心代码

视图代码

<table id="propertiestable">
@foreach (PropertyField field in Model.Fields)
{
    <tr>
        <td>@Html.DisplayName(field.Id.ToString())</td>
        <td>Property 1:</td>
        <td>
            @Html.DropDownListFor(m => m.PropertyOne, Model.ListItemsOne)                
        </td>
        <td>Property 2:</td>
        <td>
            @Html.DropDownListFor(m => m.PropertyTwo, Model.ListItemsTwo)
        </td>
        <td>Property 3:</td>
        <td>
            @Html.TextBoxFor(m => m.PropertyThree)
        </td>
        <td>
            <input class="btn btn-sm btn-danger" onclick="DeletePropClick(@field.Id)" value="X" name="RemoveProperty+@field.Id" />
        </td>
    </tr>
}

模型代码

public class PropertiesVM : EdgeActionBase {
    public List<PropertyField> Fields { get; set; }
    // 其他属性省略
}
public class PropertyField {
   public int Id { get; set; }
   public string PropertyOne { get; set; }
   public string PropertyTwo { get; set; }
   public int PropertyThree { get; set; }
}

尝试的JavaScript代码(未生效)

$('#@nameof(Model.Fields[i].PropertyOne)').on("change", function () {
alert('Hi there');
var selectedProperty = $(this).val();
var test = $(this).id();
var fields = '@Model.Fields';
let dataObj = { "Fields": fields, "PropertyOne": selectedProperty};
$.ajax({
    url: "@Url.Action("SelectPropertyOnePartial")",
    type: "POST",
    data: JSON.stringify(dataObj),
    contentType: "application/json",
    success: function (data) {
        if (data != null) {
            $("#divProperties").html(data);
        }
    }
});

问题分析与解决方案

问题根源

  1. 视图绑定错误:原代码中DropDownListFor(m => m.PropertyOne)绑定的是ViewModel的顶级属性,而非循环中的field.PropertyOne,导致所有行的下拉框共享同一个属性,无法区分不同字段ID。
  2. JS选择器无效:$('#@nameof(Model.Fields[i].PropertyOne)')中的i在Razor循环中未定义,无法生成正确的控件ID选择器,事件绑定完全失效。
  3. 数据传递错误:直接将@Model.Fields转为字符串传递到JS会导致对象序列化异常,无法正确传递数据。
  4. 更新范围错误:成功回调中刷新整个#divProperties,会重置所有行的状态,而非仅更新当前行的PropertyTwo下拉框。

修正步骤

1. 修正视图控件绑定

修改DropDownListFor的绑定目标,为PropertyOne下拉框添加自定义属性存储字段ID,同时为PropertyTwo下拉框设置唯一ID,方便后续定位更新:

<table id="propertiestable">
@foreach (PropertyField field in Model.Fields)
{
    <tr>
        <td>@field.Id</td>
        <td>Property 1:</td>
        <td>
            @* 绑定到当前field的PropertyOne,添加data-field-id存储字段ID *@
            @Html.DropDownListFor(m => field.PropertyOne, Model.ListItemsOne, 
                new { 
                    @class = "property-one-dropdown",
                    data_field_id = field.Id 
                })                
        </td>
        <td>Property 2:</td>
        <td>
            @* 为PropertyTwo设置唯一ID,格式为PropertyTwo_字段ID *@
            @Html.DropDownListFor(m => field.PropertyTwo, Model.ListItemsTwo, 
                new { 
                    id = $"PropertyTwo_{field.Id}",
                    @class = "property-two-dropdown"
                })
        </td>
        <td>Property 3:</td>
        <td>
            @Html.TextBoxFor(m => field.PropertyThree)
        </td>
        <td>
            <input class="btn btn-sm btn-danger" onclick="DeletePropClick(@field.Id)" value="X" name="RemoveProperty_@field.Id" />
        </td>
    </tr>
}

2. 修正JavaScript代码

使用事件委托绑定change事件(支持动态添加行的场景),获取当前下拉框对应的字段ID,仅更新当前行的PropertyTwo下拉框:

// 事件委托:监听表格内所有property-one-dropdown的change事件
$('#propertiestable').on('change', '.property-one-dropdown', function() {
    var $this = $(this);
    var selectedValue = $this.val();
    var fieldId = $this.data('field-id'); // 获取自定义属性中的字段ID

    if (!selectedValue) {
        // 若未选择值,清空对应PropertyTwo下拉框
        $(`#PropertyTwo_${fieldId}`).empty().append('<option value="">请选择</option>');
        return;
    }

    // 发起AJAX请求获取对应PropertyTwo选项
    $.ajax({
        url: '@Url.Action("GetPropertyTwoOptions")',
        type: 'POST',
        data: { 
            fieldId: fieldId,
            propertyOneValue: selectedValue 
        },
        success: function(options) {
            var $propertyTwo = $(`#PropertyTwo_${fieldId}`);
            $propertyTwo.empty();
            // 添加新选项
            $.each(options, function(index, item) {
                $propertyTwo.append(`<option value="${item.Value}">${item.Text}</option>`);
            });
        },
        error: function() {
            alert('获取PropertyTwo选项失败');
        }
    });
});

3. 添加后端Action方法

在Controller中添加返回PropertyTwo选项的Action,接收字段ID和PropertyOne选中值,返回SelectListItem列表:

[HttpPost]
public JsonResult GetPropertyTwoOptions(int fieldId, string propertyOneValue)
{
    // 根据fieldId和propertyOneValue从业务逻辑获取对应的PropertyTwo选项
    var options = new List<SelectListItem>
    {
        // 示例数据,实际替换为业务逻辑
        new SelectListItem { Text = "选项A", Value = "A" },
        new SelectListItem { Text = "选项B", Value = "B" }
    };

    return Json(options);
}

关键说明

  • 自定义属性data-field-id:无需解析DOM结构,直接在JS中获取当前下拉框对应的字段ID。
  • 事件委托:避免循环绑定事件,同时支持后续动态添加的行也能触发联动逻辑。
  • 局部更新:仅更新当前行的PropertyTwo下拉框,避免重置其他行的状态,提升用户体验。
  • 简化数据传递:仅传递必要的字段ID和选中值,减少数据传输量,避免序列化异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:11:16