ASP.NET MVC 5 相依關聯的下拉式選單(Dependent Dropdownlist)實作方式

2020-08-11

筆記介紹如何在 ASP.NET MVC 5 實踐相依關聯的下拉式選單 🌞

logo

說明

使用 jQuery Ajax

優點 : 後端邏輯簡單
缺點 : 互動的邏輯需要寫在前端 jQuery 中不易維護

  1. DropdownList Input 保持原樣
<div class="col-md-3">
    <div class="form-group">
        <div class="col-md-10">
            @Html.DropDownList("CityGroup", null, htmlAttributes: new { @class = "form-control" })
        </div>
    </div>
</div>
<div class="col-md-3">
    <div class="form-group">
        <div class="col-md-10">
            @Html.DropDownList("City", null, htmlAttributes: new { @class = "form-control" })
        </div>
    </div>
</div>
  1. Index Action 處理預設選項
public ActionResult Index(int? cityId)
{
    if (cityId == null)
    {
        cityId = db.City.First().Id;
    }

    var groupCity = db.City.GroupBy(i => i.GroupName).Select(g => g.FirstOrDefault()).ToList();
    string firstGroupCityName = groupCity.FirstOrDefault().GroupName;
    var city = db.City.Where(i => i.GroupName == firstGroupCityName).ToList();

    ViewBag.CityGroup = new SelectList(groupCity, "GroupName", "GroupName");
    ViewBag.City = new SelectList(city, "Id", "CityName");

    return View("Index", db.City.ToList());
}
  1. 加入 scripts
$(document).ready(function () {
    $("#CityGroup").change(function () {
        $("#City").empty();
        $.ajax({
            type: "POST",
            url: '@Url.Action("GetCityByCityGroup")',
            dataType: "json",
            data: { groupName: $("#CityGroup").val() },
            success: function (mems) {
                $.each(mems, function (i, member) {
                    $("#City").append(
                    '<option value="' + member.Value + '">' + member.Text + "</option>"
                );
                });
            },
            error: function (ex) {
                alert("Failed to retrieve states : " + ex);
            },
        }); // ajax end
        return false;
    }); // change end
}); // document ready end
  1. 設計處理動作的 controller / action 處理後回應 json result
public JsonResult GetCityByCityGroup(string groupName)
{
    return Json(new SelectList(db.City.Where(i => i.GroupName == groupName), "Id", "CityName"));
}

參考資料

使用 Ajax Unobtrusive

優點 : 易於維護
缺點 : 設計步驟較為繁雜

  1. jQuery Bundle 加入 Ajax Unobtrusive
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js",
            "~/Scripts/jquery.unobtrusive-ajax.js"));
  1. 加入 @Ajax.BeginForm 包住 dropdownlist

實作關鍵:

<div class="col-md-3">
    <div class="form-group">
        <div class="col-md-10">
            @using (Ajax.BeginForm(
              "GetCityPartialViewByCityGroup",
              "Cities",
              new AjaxOptions { UpdateTargetId = "City" }))
            {
                @Html.DropDownList("CityGroup",
                 null,
                 htmlAttributes:
                 new { @class = "form-control",
                 @onChange = "$(this.form).submit();" })
            }
        </div>
    </div>
</div>
<div class="col-md-3">
    <div class="form-group">
        <div class="col-md-10">
            @Html.DropDownList("City", null, htmlAttributes: new { @class = "form-control" })
        </div>
    </div>
</div>
  1. dropdownlist 加入 onChange commit form
@Html.DropDownList("CityGroup", null,
  htmlAttributes:  new { @class = "form-control",
  @onChange = "$(this.form).submit();" })
  1. 設計處理動作的 controller / action 處理後回應 partial view
public ActionResult GetCityPartialViewByCityGroup(string CityGroup)
{
    return View(db.City.Where(i => i.GroupName == CityGroup));
}
  1. 設計 partial view 的內容,根據條件生成 Select Options
@model IEnumerable<ChartJS_WebAPI.Models.City>
@{
    Layout = null;
}

@foreach (var item in Model)
{
    <option value="@item.Id">@item.CityName</option>
}

參考資料