jquery 多选 - 从数据库分组

jquery multiselect - grouping from database

我正在使用 jquery 多选插件 [https://github.com/davidstutz/bootstrap-multiselect] 并将其与数据库值动态绑定。

HTML

@Html.ListBoxFor(m => m.Classes, new SelectList(Model.Classes, "Value", "Text"), new { @id = "classList" })

脚本

$('#classList').multiselect({ enableClickableOptGroups: true });

视图中的模型是一个视图模型,包含一个 属性 一个 SelectList

public class SearchControlViewModel 
{
    ....
    public SelectList Classes { get; set; }
}

和控制器中的代码

SearchControlViewModel  model = new SearchControlViewModel()
{
    ....
    Classes = new SelectList(repClass.GetClassesByYear(23), "classID", "classname")
};
return View(model);

除一件事外,它就像一个魅力 - 我想像 <optgroup> 一样添加 grouping/group header。我该怎么做?

GetClassesByYear() 方法用于生成 SelectList returns 一个包含属性 int classIDstring classnamestring grade 的 object ] 并且我希望能够按 grade.

对选项进行分组

MVC-4 不支持选项组,您需要升级到 MVC-5 才能使用开箱即用的功能。如果您要升级,请参阅 以获取使用 SelectList 构造函数并生成 IEnumerable<SelectListItem>

的示例

无需升级,您可以将表示您的组及其选项的模型传递给视图,并使用一些 javascript/jquery 来生成元素。首先创建一些额外的视图模型

public class OptionGroupVM
{
    public string GroupName { get; set; }
    public IEnumerable<OptionVM> Options { get; set; }
}
public class OptionVM
{
    public string Value { get; set; }
    public string Text { get; set; }
    public bool IsSelected { get; set; } // Only applicable if your not binding to a model property
}

然后修改您的主视图模型以包含以下内容

public class SearchControlViewModel 
{
    ....
    public IEnumerable<int> SelectedClasses { get; set; }
    public IEnumerable<OptionGroupVM> ClassOptions { get; set; }
}

请注意,您当前的模型和使用 ListBoxFor() 是不正确的,因为

  1. 您不能将 <select multiple> 绑定到您的 Classes 属性 的复杂对象集合 - 模型需要是值类型的集合,和

  2. 您不能为您绑定的 属性 和 SelectList 使用相同的名称 - 请参阅 了解更多详细信息

在控制器中

var data = repClass.GetClassesByYear(23);
var groupedOptions = data.GroupBy(x => x.grade).Select(x => new OptionGroupVM()
{
    GroupName = x.Key.ToString(),
    Options = x.Select(y => new OptionVM()
    {
        Value = y.classId.ToString(),
        Text = y.classcame,
    })
});
SearchControlViewModel model = new SearchControlViewModel()
{
    ....
    SelectedClasses = ...., // the values of the options that will be pre-selected
    ClassOptions = groupedOptions
};
return View(model);

并在视图中使用

@Html.ListBoxFor(m => SelectedClasses, Enumerable.Empty<SelectListItem>(), new { id = "classList" })

最初会生成 <select> 而不带任何选项。然后使用以下脚本生成选项

<script type="text/javascript">
    // Get data
    var listBox = $('#classList');
    var selected = @Html.Raw(Json.Encode(Model.SelectedClasses));
    var groups = @Html.Raw(Json.Encode(Model.ClassOptions));

    // Generate options
    createGroupedOptions(listBox, selected, groups);
    // Attach plug-in
    listBox.multiselect({ enableClickableOptGroups: true });

    // This function could be in an external js file
    function createGroupedOptions(element, selected, groups) {
        for (var i = 0; i < groups.length; i++) {
            var group = groups[i];
            var groupElement = $('<optgroup></optgroup>').attr('label', group.GroupName);
            for(var j = 0; j < group.Options.length; j++) {
                var option = group.Options[j];
                var optionElement = $('<option></option>').val(option.Value).text(option.Text);
                if (selected) {
                    if (selected.toString().indexOf(option.Value) >= 0) {
                        optionElement.attr('selected', 'selected')
                    }
                } else {
                    if (option.IsSelected) {
                        optionElement.attr('selected', 'selected')
                    }
                }

                $(groupElement).append(optionElement);
            }
            $(element).append(groupElement);
        }
    }
</script>