บางครั้งเวลาออกแบบ navigation ของเว็บ เราอาจจะมีโอกาสใช้ select
เพื่อให้ผู้ใช้ระบุเงื่อนไขที่ต้องการ และแสดงเงื่อนไขปัจจุบันที่ใช้งานอยู่ด้วย ตัวอย่างเช่น Jitta ใช้ select
เพื่อให้ผู้ใช้เลือกเงื่อนไขตลาดที่จะแสดง และแสดงว่าปัจจุบันแสดงข้อมูลตลาดไหนอยู่(ใช้ selectize.js
ทำ)
สำหรับ Select Tag Helper ใน MVC 6 นั้นมีอยู่ 2 อย่างที่ใช้คือ asp-for
สำหรับกำหนดตัวแปรที่จะเก็บค่าที่ถูกเลือกไว้ใน select
(เหมือนกับ input tag อื่นๆ)และ asp-item
เพื่อระบุว่าจะแสดงอะไรให้เลือกได้บ้างใน select ในที่นี้ผมจะไม่พูดถึง asp-for เพราะคิดว่าใช้กันเป็นแล้ว มาดูที่ asp-item กัน
asp-item รับค่าประเภท SelectList ดู constructor ของคลาส SelectList ได้ที่ SelectList Constructor จากที่เห็นเราสามารถกำหนดค่าที่จะถูกเลือกได้ง่ายๆ ดังนี้
ที่ controller
1 2 3 4 5 6 |
... var list = new List<string> { "One", "Two", "Three" }; var selectItems = new SelectList(list, "Two"); // argument ตัวที่ 2 ใช้ระบุค่าเริ่มต้นที่จะเลือก viewModel.SelectItems = selectItems; ... return View(viewModel); |
ที่ view
1 |
<select asp-for="@Model.Number" asp-item="@Model.SelectItems"></select> |
ถ้าดูจากเอกสารของ constructor ก็จะเห็นว่าด้วยวิธีนี้สามารถควบคุมค่าเริ่มต้นที่จะถูกแสดงได้ง่ายๆ
กรณีใช้ Enum แสดงผล
Html Helper มี method ชื่อ GetEnumSelectList(Type enumType) ซึ่งจะแปลง enum มาแสดง
1 2 3 4 5 6 |
public enum Number { One, Two, Tree } |
ที่ view
1 |
<select asp-for="@Model.Number" asp-item="@Html.GetEnumSelectList(typeof(Number))"></select> |
แต่ปัญหากับ Enum คือมันจะเลือกค่าเริ่มต้นจาก Enum แรกสุดเสมอ ในตัวอย่างนี้คือ One
วิธีแก้คือเขียน Html Helper ขึ้นมาเอง เพิ่ม parameter ให้รับค่าเริ่มต้นที่จะแสดงเข้ามา
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public static IEnumerable<SelectListItem> GetEnumSelectList<TEnum>(this IHtmlHelper h,Type type, TEnum selectValue) { if (!type.GetTypeInfo().IsEnum) { throw new ArgumentException("type must be enum type", "type"); } var selectItemList = new List<SelectListItem>(); var names = Enum.GetNames(type); var values = (int[])Enum.GetValues(type); var selected = Enum.GetName(type, selectValue); for (var i = 0; i < names.Length; i++) { var field = type.GetField(names[i]); var displayName = GetDisplayName(field); var selectListItem = new SelectListItem { Text = displayName, Value = values[i].ToString() }; if (selectListItem.Text == selected) { selectListItem.Selected = true; } selectItemList.Add(selectListItem); } return selectItemList; } private static string GetDisplayName(FieldInfo field) { var display = field.GetCustomAttribute<DisplayAttribute>(false); if (display != null) { var name = display.GetName(); if (!string.IsNullOrEmpty(name)) { return name; } } return field.Name; } |
ใช้ reflect อ่าน attribute เพื่อแก้ชื่อที่แสดงตามที่ผู้ใช้อาจจะใส่
เวลาใช้ที่ View
1 |
<select asp-for="@Model.Number" asp-item="@Html.GetEnumSelectList(typeof(Number), Number.Two)"></select> |
เป็นอันจบ