カスケーディング ドロップダウンリスト

2016/10/04

多段のドロップダウンリストを連動させる

一段のみの続きです。
ddl040.png

よくある大分類、中分類、小分類と絞り込んでいくような場合に複数のドロップダウンリストを設置し、一つ目のドロップダウンリストを選択したら、2つ目のドロップダウンリストの値がセットされるやつです。
検索する時は Cascading DropDownList MVCでしましょう。
もしかしてC#(Razor)だけでは無理?と言うことで、サンプル通りJavaScriptで。

詳細(商品)データ用モデル

public class Goods
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string CategoryId { get; set; }
    public decimal Price { get; set; }
}

商品一覧を返すサービス

public static List<Goods> GetGoodsAll()
{
    return new List<Goods> { 
        new Goods{Id = "001", Name = "みかん", CategoryId = "001", Price = 200},
        new Goods{Id = "002", Name = "バナナ", CategoryId = "001", Price = 100},
        new Goods{Id = "003", Name = "いちご", CategoryId = "001", Price = 400},
        new Goods{Id = "004", Name = "りんご", CategoryId = "001", Price = 150},
        new Goods{Id = "005", Name = "ブドウ", CategoryId = "001", Price = 300},
        new Goods{Id = "006", Name = "トマト", CategoryId = "002", Price = 200},
        new Goods{Id = "007", Name = "キュウリ", CategoryId = "002", Price = 180},
        new Goods{Id = "008", Name = "レタス", CategoryId = "002", Price = 160},
    };
}

JavaScript用のApiを追加

public class GoodsController : ApiController
{
    [HttpGet]
    public IEnumerable<Goods> GetGoodsById(string id = "000")
    {
        return GoodsService.GetGoodsAll().Where(m => m.CategoryId == id);
    }
}

ViewModelの変更

[Display(Name = "分類")]
[Required]
public string SelectCategoryId { get; set; }

public SelectList CategoryList { get; set; }
//public IEnumerable<SelectListItem> CategoryList { get; set; }

// 下記部分を追加
[Display(Name = "商品")]
[Required]
public string SelectGoodsId { get; set; }

public SelectList GoodsList { get; set; }

Viewの変更

@model Sample.Models.DDLViewModel
@{
    ViewBag.Title = "Index";
}
<h2>カスケーディング ドロップダウンリスト</h2>
<div>
    @using (Html.BeginForm())
    {
        <div class="form-group">
            @Html.LabelFor(m => m.SelectCategoryId)
            @Html.DropDownListFor(m => m.SelectCategoryId, Model.CategoryList, "選択してください", new { @class = "form-control", id = "CategoryList" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.SelectGoodsId)
            @Html.DropDownListFor(m => m.SelectGoodsId, new SelectListItem[] { new SelectListItem { Text = "選択してください", Value = string.Empty } }, new { @class = "form-control", id = "GoodsList" })
        </div>
        <div>
            <input type="submit" value="送信" class="btn btn-primary" />
        </div>
    }
</div>
@section scripts{
     <script>
         $('#CategoryList').change(function () {
             var URL = '/api/goods/GetGoodsById';
             $.getJSON(URL + '/' + $('#CategoryList').val(), function (data) {
                 var items = '<option>選択してください</option>';
                 $.each(data, function (i, goods) {
                     items += "<option value='" + goods.Id + "'>" + goods.Name + "</option>";
                 });
                 $('#GoodsList').html(items);
             });
         });
     </script>
}
2個目のドロップダウンリストも@Html.DropDownListForを使用。
jQuery用にそれぞれのドロップダウンリストにidを追加します。

SelectListItemにNull渡すと怒られたので、「選択してください」をセット。
1個目のドロップダウンリスト選択後、jQueryで差し替えます。

サンプルに沿いつつできるだけシンプルにしてみました(省きすぎてバグっていたらすみません)。

実行結果

ddl030.png

一応動きました。
ポストバック時に値を保持するバージョンに続く。
OK キャンセル 確認 その他