ASP.NET Coreでチェックボックスリストの作り方。チェックされた項目の取得方法
画像中段のようなチェックボックスのリストを使う機会が多い.
選択状態を表示させ,ユーザーによる選択の状態をサーバー側に送ったりする.
例えば,以下のようなViewModelを使うとする.
このViewModelはItemsというリストを持っていて,そのリストの要素Itemは選択状態を保持するIsSelected
プロパティを持っている.
とする.
このアイテムのチェックボックスリストを表示し,ユーザーに選択させてそれをサーバー側で受け取り,DBなどに保存する.
ということがよくある.
//ViewModel public class PersonViewModel { public string Name { get; set; } public decimal Age { get; set; } public IList<Item> Items { get; set; } } //Itemモデル public class Item { public string Name { get; set; } public decimal Price { get; set; } public bool IsSelected { get; set; } }
これをView側で以下のように表示させる.
@model CheckboxPractice.ViewModels.PersonViewModel <form method="post" action="checkboxlist"> <div class="card"> <div class="card-header"> <div class=""> @Model.Name <input type="hidden" asp-for="@Model.Name" />//サーバー側で受け取るため </div> <div class=""> @Model.Age <input type="hidden" asp-for="@Model.Age" />//サーバー側で受け取るため </div> </div> <div class="card-body"> @for (var i = 0; i < Model.Items.Count; i++)//foreachではだめ.必ずforを使うこと. { @* サーバー側に値が渡るようにするためにはInput要素であることが必要 *@ <input type="hidden" asp-for="@Model.Items[i].Name" />//サーバー側で受け取るため <input type="hidden" asp-for="@Model.Items[i].Price" />//サーバー側で受け取るため @* bool型のプロパティをasp-forに指定すると,自動的にチェックボックスに変換される *@ <input asp-for="@Model.Items[i].IsSelected" /> <label asp-for="@Model.Items[i].IsSelected"> @Model.Items[i].Name </label> } </div> <div class="card-footer"> <button type="submit">送信</button> </div> </div> </form>
重要ポイント
<input>
タグのasp-for
に指定したプロパティしかサーバー側に渡されない.- つまり,サーバー側に渡したいプロパティは
<input>
タグを使うこと! - 表示させない隠し情報とするなら
type="hidden"
にする. - ループでチェックボックスをリスト上に作成する場合は,
for
を使うこと! - foreachではチェック操作が期待したように動作しない
- そして選択状態もサーバー側に期待したとおりに渡らない
foreachを使った場合に生成されるHTMLをブラウザの開発者ツールでみてみると,checkboxの部分のname属性の値がどれも同じname="item.IsSelected"
になっている.
<div class="card-body"> <input type="hidden" id="item_Name" name="item.Name" value="Erazer"> <input type="hidden" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="item_Price" name="item.Price" value="100"> <input type="checkbox" data-val="true" data-val-required="The IsSelected field is required." id="item_IsSelected" name="item.IsSelected" value="true"> <label for="item_IsSelected"> Erazer </label> <input type="hidden" id="item_Name" name="item.Name" value="Pencil"> <input type="hidden" id="item_Price" name="item.Price" value="100"> <input type="checkbox" id="item_IsSelected" name="item.IsSelected" value="true"> <label for="item_IsSelected"> Pencil </label> <input type="hidden" id="item_Name" name="item.Name" value="Notebook"> <input type="hidden" id="item_Price" name="item.Price" value="100"> <input type="checkbox" id="item_IsSelected" name="item.IsSelected" value="true"> <label for="item_IsSelected"> Notebook </label> </div>
それに対してforを使った場合は以下のように,name="Items[0].IsSelected"
,name="Items[1].IsSelected"
,name="Items[2].IsSelected"
というようにリストの各要素に対応するようになっている.
<div class="card-body"> <input type="hidden" id="Items_0__Name" name="Items[0].Name" value="Erazer"> <input type="hidden" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Items_0__Price" name="Items[0].Price" value="100"> <input type="checkbox" data-val="true" data-val-required="The IsSelected field is required." id="Items_0__IsSelected" name="Items[0].IsSelected" value="true"> <label for="Items_0__IsSelected"> Erazer </label> <input type="hidden" id="Items_1__Name" name="Items[1].Name" value="Pencil"> <input type="hidden" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Items_1__Price" name="Items[1].Price" value="100"> <input type="checkbox" data-val="true" data-val-required="The IsSelected field is required." id="Items_1__IsSelected" name="Items[1].IsSelected" value="true"> <label for="Items_1__IsSelected"> Pencil </label> <input type="hidden" id="Items_2__Name" name="Items[2].Name" value="Notebook"> <input type="hidden" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Items_2__Price" name="Items[2].Price" value="100"> <input type="checkbox" data-val="true" data-val-required="The IsSelected field is required." id="Items_2__IsSelected" name="Items[2].IsSelected" value="true"> <label for="Items_2__IsSelected"> Notebook </label> </div>
このようにforとforeachでは生成されるHTMLが異なることが理由で,forじゃないと値がサーバー側に渡らない.