使用 AJAX 来源填充 MVC DropdownList 并绑定所选值

Filling MVC DropdownList with AJAX source and bind selected value

我有显示会员详细信息的视图。里面有一个 EditorFor 元素,它代表成员拍摄的主题。

 @Html.EditorFor(m => m.Subject)

在编辑器模板中有一个 Html.DropDownListFor() 显示所选主题和删除该主题的按钮

我正在使用 Html.DropDownListFor 元素作为 :

@Html.DropDownListFor(m => m.SubjectID, Enumerable.Empty<SelectListItem>(), "Select Subject", 
new { @class = "form-control subjects" }) 

第二个参数(source)设置为空,因为我想从 AJAX 请求中加载源;如下所示:

$.getJSON(url, function (response) {
         $.each(response.Subjects, function (index, item) { 
                $('.subjects').append($('<option></option>').text(item.Text).val(item.ID));
            });
         // code to fill other dropdowns
    });

当前 html 在下拉列表被填充之前加载。因此,所有主题下拉列表的值都设置为默认值 "Select Subject"。有没有办法解决这个问题或者这是错误的方法?

注意:此页面中有许多下拉菜单。这就是为什么我宁愿给它们加载一个 AJAX 请求并缓存它,而不是放入 viewModel 并为每个请求填充它。

** 编辑 **

在 AJAX 调用中,操作 returns 一个 json 对象,其中包含用于所有页面的下拉菜单。此操作用 [Output Cache] 修饰,以避免频繁访问服务器。更改了 $.each 中的代码以反映这一点。

如果您的 JSON 告诉您他们有什么选项 select 您可以在填充下拉列表后简单地执行以下操作:

$('.form-control.subjects').get(0).selectedIndex = [SELECTED_INDEX];

其中 [SELECTED_INDEX] 是您要 select 在下拉列表中的元素的索引。

您可以最初将 属性 的值分配给 javascript 变量,并在选项具有后使用它在 ajax 回调中设置所选选项的值已追加。

// Store initial value
var selectedId = @Html.Raw(Json.Encode(Model.Subject.SubjectID))
var subjects = $('.subjects'); // cache it

$.getJSON(url, function (response) {
    $.each(response, function (index, item) { 
        subjects.append($('<option></option>').text(item.Text).val(item.ID));
    });
    // Set selected option
    subjects.val(selectedId);
});

但是不清楚您为什么要进行 ajax 调用,除非您正在生成级联下拉列表,但事实并非如此。你所做的基本上是对客户说 - 这里有一些数据,但我忘了发送你需要的东西,所以浪费更多的时间和资源建立另一个连接来获取其余数据.不管你怎么想,你都没有缓存任何东西。

如果另一方面,您的 Subject 属性 实际上是对象的集合(在这种情况下,它应该是 Subjects - 复数),那么正确的方法是使用EditorTemplate 的选项 1 中有解释。


另请注意,如果 Subject 是一个集合,则需要修改上面的 var selectedId = .. 代码以生成 SubjectID 值的数组,例如

var selectedIds = @Html.Raw(Json.Encode(Model.Subject.Select(x => x.SubjectID)))

然后需要循环设置每个下拉列表值

$.each(subjects, function(index, item) {
    $(this).val(selectedIds[index]);
});