Pilih Tag Helper di ASP.NET Core MVC

162

Saya butuh bantuan dengan penolong tag pilih di ASP.NET Core.

Saya memiliki daftar karyawan yang saya coba ikat ke penolong tag tertentu. Karyawan saya ada di List<Employee> EmployeesListdan nilai yang dipilih akan masuk ke EmployeeIdproperti. Model tampilan saya terlihat seperti ini:

public class MyViewModel
{
   public int EmployeeId { get; set; }
   public string Comments { get; set; }
   public List<Employee> EmployeesList {get; set; }
}

Kelas karyawan saya terlihat seperti ini:

public class Employee
{
   public int Id { get; set; }
   public string FullName { get; set; }
}

Pertanyaan saya adalah bagaimana saya memberi tahu penolong tag pilih saya untuk menggunakan Idsebagai nilai saat ditampilkan FullNamedalam daftar drop-down?

<select asp-for="EmployeeId" asp-items="???" />

Saya menghargai bantuan dengan ini. Terima kasih.

Sam
sumber
3
hanya sesuatu yang saya pikir harus saya tambahkan, tampaknya tidak berfungsi jika Anda segera menutup tag pilih selalu tutup tag dengan </select> tag helper tidak berfungsi dengan <select asp-for ..... />
RoughPlace
hanya sebuah tip. pengendali perancah menunjukkan umumnya menunjukkan kepada Anda cara terbaik untuk hal-hal seperti itu
Neville Nazerane

Jawaban:

379

Menggunakan bantuan Tag Pilih untuk merender elemen SELECT

Dalam tindakan GET Anda, buat objek model tampilan Anda, muat EmployeeListproperti koleksi dan kirimkan ke tampilan.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.EmployeesList = new List<Employee>
    {
        new Employee { Id = 1, FullName = "Shyju" },
        new Employee { Id = 2, FullName = "Bryan" }
    };
    return View(vm);
}

Dan di tampilan buat Anda, buat SelectListobjek baru dari EmployeeListproperti dan berikan itu sebagai nilai untuk asp-itemsproperti.

@model MyViewModel
<form asp-controller="Home" asp-action="Create">

    <select asp-for="EmployeeId" 
            asp-items="@(new SelectList(Model.EmployeesList,"Id","FullName"))">
        <option>Please select one</option>
    </select>

    <input type="submit"/>

</form>

Dan metode tindakan HttpPost Anda untuk menerima data formulir yang dikirimkan.

[HttpPost]
public IActionResult Create(MyViewModel model)
{
   //  check model.EmployeeId 
   //  to do : Save and redirect
}

Atau

Jika model tampilan Anda memiliki List<SelectListItem>sebagai properti untuk item dropdown Anda.

public class MyViewModel
{
    public int EmployeeId { get; set; }
    public string Comments { get; set; }
    public List<SelectListItem> Employees { set; get; }
}

Dan dalam tindakan Anda,

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Sean", Value = "2"}
    };
    return View(vm);
}

Dan dalam tampilan, Anda dapat langsung menggunakan Employeesproperti untuk asp-items.

@model MyViewModel
<form asp-controller="Home" asp-action="Create">

    <label>Comments</label>
    <input type="text" asp-for="Comments"/>

    <label>Lucky Employee</label>
    <select asp-for="EmployeeId" asp-items="@Model.Employees" >
        <option>Please select one</option>
    </select>

    <input type="submit"/>

</form>

Kelas SelectListItemmilik Microsoft.AspNet.Mvc.Renderingnamespace.

Pastikan Anda menggunakan tag penutup eksplisit untuk elemen pilih. Jika Anda menggunakan pendekatan tag penutup diri, tag helper akan membuat elemen SELECT kosong!

Pendekatan di bawah ini tidak akan berhasil

<select asp-for="EmployeeId" asp-items="@Model.Employees" />

Tetapi ini akan berhasil.

<select asp-for="EmployeeId" asp-items="@Model.Employees"></select>

Mendapatkan data dari tabel database Anda menggunakan framework entitas

Contoh di atas menggunakan item kode keras untuk opsi. Jadi saya pikir saya akan menambahkan beberapa kode sampel untuk mendapatkan data menggunakan kerangka kerja Entity karena banyak orang menggunakannya.

Mari kita asumsikan objek DbContext Anda memiliki properti yang disebut Employees, yang merupakan tipe di DbSet<Employee>mana Employeekelas entitas memiliki Iddan Nameproperti seperti ini

public class Employee
{
   public int Id { set; get; }
   public string Name { set; get; }
}

Anda bisa menggunakan kueri LINQ untuk mendapatkan karyawan dan menggunakan metode Pilih dalam ekspresi LINQ Anda untuk membuat daftar SelectListItemobjek untuk setiap karyawan.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = context.Employees
                          .Select(a => new SelectListItem() {  
                              Value = a.Id.ToString(),
                              Text = a.Name
                          })
                          .ToList();
    return View(vm);
}

Dengan asumsi contextadalah objek konteks db Anda. Kode tampilan sama seperti di atas.

Menggunakan SelectList

Beberapa orang lebih suka menggunakan SelectListkelas untuk menyimpan item yang diperlukan untuk memberikan opsi.

public class MyViewModel
{
    public int EmployeeId { get; set; }
    public SelectList Employees { set; get; }
}

Sekarang dalam tindakan GET Anda, Anda bisa menggunakan SelectListkonstruktor untuk mengisi Employeesproperti model tampilan. Pastikan Anda menentukan parameter dataValueFielddan dataTextField.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new SelectList(GetEmployees(),"Id","FirstName");
    return View(vm);
}
public IEnumerable<Employee> GetEmployees()
{
    // hard coded list for demo. 
    // You may replace with real data from database to create Employee objects
    return new List<Employee>
    {
        new Employee { Id = 1, FirstName = "Shyju" },
        new Employee { Id = 2, FirstName = "Bryan" }
    };
}

Di sini saya memanggil GetEmployeesmetode untuk mendapatkan daftar objek Karyawan, masing-masing dengan Iddan FirstNameproperti dan saya menggunakan properti tersebut sebagai DataValueFielddan DataTextFielddari SelectListobjek yang kami buat. Anda dapat mengubah daftar hardcoded ke kode yang membaca data dari tabel database.

Kode tampilan akan sama.

<select asp-for="EmployeeId" asp-items="@Model.Employees" >
    <option>Please select one</option>
</select>

Render elemen SELECT dari daftar string.

Kadang-kadang Anda mungkin ingin membuat elemen pilih dari daftar string. Dalam hal ini, Anda dapat menggunakan SelectListkonstruktor yang hanya dibutuhkanIEnumerable<T>

var vm = new MyViewModel();
var items = new List<string> {"Monday", "Tuesday", "Wednesday"};
vm.Employees = new SelectList(items);
return View(vm);

Kode tampilan akan sama.

Pengaturan opsi yang dipilih

Beberapa kali, Anda mungkin ingin menetapkan satu opsi sebagai opsi default di elemen SELECT (Misalnya, di layar edit, Anda ingin memuat nilai opsi yang disimpan sebelumnya). Untuk melakukan itu, Anda cukup mengatur nilai EmployeeIdproperti ke nilai opsi yang ingin Anda pilih.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "11"},
        new SelectListItem {Text = "Tom", Value = "12"},
        new SelectListItem {Text = "Jerry", Value = "13"}
    };
    vm.EmployeeId = 12;  // Here you set the value
    return View(vm);
}

Ini akan memilih opsi Tom di elemen pilih ketika halaman diberikan.

Dropdown multi pilih

Jika Anda ingin merender dropdown multi pilih, Anda cukup mengubah properti model tampilan yang Anda gunakan untuk asp-foratribut dalam tampilan Anda menjadi tipe array.

public class MyViewModel
{
    public int[] EmployeeIds { get; set; }
    public List<SelectListItem> Employees { set; get; }
}

Ini akan membuat markup HTML untuk elemen pilih dengan multipleatribut yang akan memungkinkan pengguna untuk memilih beberapa opsi.

@model MyViewModel
<select id="EmployeeIds" multiple="multiple" name="EmployeeIds">
    <option>Please select one</option>
    <option value="1">Shyju</option>
    <option value="2">Sean</option>
</select>

Pengaturan opsi yang dipilih dalam multi pilih

Mirip dengan pemilihan tunggal, atur nilai EmployeeIdsproperti ke array nilai yang Anda inginkan.

public IActionResult Create()
{
    var vm = new MyViewModel();
    vm.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "11"},
        new SelectListItem {Text = "Tom", Value = "12"},
        new SelectListItem {Text = "Jerry", Value = "13"}
    };
    vm.EmployeeIds= new int[] { 12,13} ;  
    return View(vm);
}

Ini akan memilih opsi Tom and Jerry di elemen multi-pilih ketika halaman diberikan.

Menggunakan ViewBag untuk mentransfer daftar item

Jika Anda tidak memilih untuk menyimpan properti tipe koleksi untuk meneruskan daftar opsi ke tampilan, Anda dapat menggunakan ViewBag dinamis untuk melakukannya. ( Ini bukan pendekatan yang saya sarankan secara pribadi karena viewbag dinamis dan kode Anda cenderung tidak ditambal kesalahan ketik )

public IActionResult Create()
{       
    ViewBag.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Sean", Value = "2"}
    };
    return View(new MyViewModel());
}

dan dalam tampilan

<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
    <option>Please select one</option>
</select>

Menggunakan ViewBag untuk mentransfer daftar item dan mengatur opsi yang dipilih

Sama seperti di atas. Yang harus Anda lakukan adalah, atur nilai properti (yang Anda ikatkan dropdown untuk) ke nilai opsi yang ingin Anda pilih.

public IActionResult Create()
{       
    ViewBag.Employees = new List<SelectListItem>
    {
        new SelectListItem {Text = "Shyju", Value = "1"},
        new SelectListItem {Text = "Bryan", Value = "2"},
        new SelectListItem {Text = "Sean", Value = "3"}
    };

    vm.EmployeeId = 2;  // This will set Bryan as selected

    return View(new MyViewModel());
}

dan dalam tampilan

<select asp-for="EmployeeId" asp-items="@ViewBag.Employees">
    <option>Please select one</option>
</select>

Mengelompokkan item

Metode tag pembantu pilih mendukung opsi pengelompokan dalam dropdown. Yang harus Anda lakukan adalah, tentukan nilai Groupproperti masing-masing SelectListItemdalam metode tindakan Anda.

public IActionResult Create()
{
    var vm = new MyViewModel();

    var group1 = new SelectListGroup { Name = "Dev Team" };
    var group2 = new SelectListGroup { Name = "QA Team" };

    var employeeList = new List<SelectListItem>()
    {
        new SelectListItem() { Value = "1", Text = "Shyju", Group = group1 },
        new SelectListItem() { Value = "2", Text = "Bryan", Group = group1 },
        new SelectListItem() { Value = "3", Text = "Kevin", Group = group2 },
        new SelectListItem() { Value = "4", Text = "Alex", Group = group2 }
    };
    vm.Employees = employeeList;
    return View(vm);
}

Tidak ada perubahan dalam kode tampilan. pembantu tag pilih sekarang akan memberikan opsi di dalam 2 item grup optg .

Shyju
sumber
1
Terima kasih! Jenis seperti sintaks silet yang lama di mana kita perlu melakukan konversi ke SelectList. Terima kasih lagi.
Sam
7
Saya mencari cara menambahkan opsi kosong, terima kasih telah menggunakan<option>Please select one</option>
Serj Sagan
5
Perhatikan bahwa Anda HARUS memiliki tag </select> penutup - tag ini tidak akan berfungsi jika Anda mencoba menutup sendiri tag pilihan seperti <select ... />. Selain itu, jika Anda menggunakan opsi kosong seperti "Silakan pilih satu", Anda harus memberinya nilai string kosong "" agar validasi bidang yang diperlukan berfungsi.
Andy
3
"Pastikan Anda menggunakan tag penutup eksplisit untuk elemen pilih. Jika Anda menggunakan pendekatan tag penutup otomatis, tag penolong akan membuat elemen SELECT kosong!" Ini adalah masalah dalam kasus saya. Bersulang!
Mariusz
2
Terima kasih telah berusaha keras untuk jawaban ini!
Vidar
11

Saya membuat Antarmuka dan <options>penolong tag untuk ini. Jadi saya tidak perlu mengubah IEnumerable<T>item menjadi IEnumerable<SelectListItem>setiap kali saya harus mengisi <select>kontrol.

Dan saya pikir itu bekerja dengan indah ...

Penggunaannya seperti:

<select asp-for="EmployeeId">
    <option value="">Please select...</option>
    <options asp-items="@Model.EmployeesList" />
</select>

Dan untuk membuatnya bekerja dengan tag helper, Anda harus mengimplementasikan antarmuka itu di kelas Anda:

public class Employee : IIntegerListItem
{
   public int Id { get; set; }
   public string FullName { get; set; }

   public int Value { return Id; }
   public string Text{ return FullName ; }
}

Ini adalah kode yang diperlukan:

Antarmuka:

public interface IIntegerListItem
{
    int Value { get; }
    string Text { get; }
}

The <options>tag helper:

[HtmlTargetElement("options", Attributes = "asp-items")]
public class OptionsTagHelper : TagHelper
{
    public OptionsTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }

    [HtmlAttributeNotBound]
    public IHtmlGenerator Generator { get; set; }

    [HtmlAttributeName("asp-items")]
    public object Items { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.SuppressOutput();
        // Is this <options /> element a child of a <select/> element the SelectTagHelper targeted?
        object formDataEntry;
        context.Items.TryGetValue(typeof(SelectTagHelper), out formDataEntry);

        var selectedValues = formDataEntry as ICollection<string>;
        var encodedValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        if (selectedValues != null && selectedValues.Count != 0)
        {
            foreach (var selectedValue in selectedValues)
            {
                encodedValues.Add(Generator.Encode(selectedValue));
            }
        }

        IEnumerable<SelectListItem> items = null;
        if (Items != null)
        {
            if (Items is IEnumerable)
            {
                var enumerable = Items as IEnumerable;
                if (Items is IEnumerable<SelectListItem>)
                    items = Items as IEnumerable<SelectListItem>;
                else if (Items is IEnumerable<IIntegerListItem>)
                    items = ((IEnumerable<IIntegerListItem>)Items).Select(x => new SelectListItem() { Selected = false, Value = ((IIntegerListItem)x).Value.ToString(), Text = ((IIntegerListItem)x).Text });
                else
                    throw new InvalidOperationException(string.Format("The {2} was unable to provide metadata about '{1}' expression value '{3}' for <options>.",
                        "<options>",
                        "ForAttributeName",
                        nameof(IModelMetadataProvider),
                        "For.Name"));
            }
            else
            {
                throw new InvalidOperationException("Invalid items for <options>");
            }

            foreach (var item in items)
            {
                bool selected = (selectedValues != null && selectedValues.Contains(item.Value)) || encodedValues.Contains(item.Value);
                var selectedAttr = selected ? "selected='selected'" : "";

                if (item.Value != null)
                    output.Content.AppendHtml($"<option value='{item.Value}' {selectedAttr}>{item.Text}</option>");
                else
                    output.Content.AppendHtml($"<option>{item.Text}</option>");
            }
        }
    }
}

Mungkin ada kesalahan ketik tetapi tujuannya jelas saya pikir. Saya harus mengedit sedikit.

Yves
sumber
4

Anda juga dapat menggunakan IHtmlHelper.GetEnumSelectList.

    // Summary:
    //     Returns a select list for the given TEnum.
    //
    // Type parameters:
    //   TEnum:
    //     Type to generate a select list for.
    //
    // Returns:
    //     An System.Collections.Generic.IEnumerable`1 containing the select list for the
    //     given TEnum.
    //
    // Exceptions:
    //   T:System.ArgumentException:
    //     Thrown if TEnum is not an System.Enum or if it has a System.FlagsAttribute.
    IEnumerable<SelectListItem> GetEnumSelectList<TEnum>() where TEnum : struct;
Amir Rezaei
sumber
4

Jawaban saya di bawah ini tidak memecahkan pertanyaan tetapi berkaitan dengan.

Jika seseorang menggunakan enummodel kelas, seperti contoh ini:

public enum Counter
{
    [Display(Name = "Number 1")]
    No1 = 1,
    [Display(Name = "Number 2")]
    No2 = 2,
    [Display(Name = "Number 3")]
    No3 = 3
}

Dan properti untuk mendapatkan nilai saat mengirimkan:

public int No { get; set; }

Di halaman pisau cukur, Anda bisa menggunakan Html.GetEnumSelectList<Counter>()untuk mendapatkan properti enum.

<select asp-for="No" asp-items="@Html.GetEnumSelectList<Counter>()"></select>

Ini menghasilkan HTML berikut:

<select id="No" name="No">
    <option value="1">Number 1</option>
    <option value="2">Number 2</option>
    <option value="3">Number 3</option>
</select>
Itu
sumber
3

Anda dapat menggunakan kode di bawah ini untuk beberapa pilihan :

<select asp-for="EmployeeId"  multiple="multiple" asp-items="@ViewBag.Employees">
    <option>Please select</option>
</select>

Anda juga bisa menggunakan:

<select id="EmployeeId" name="EmployeeId"  multiple="multiple" asp-items="@ViewBag.Employees">
    <option>Please select</option>
</select>
Zubayer Bin Ayub
sumber
0

Di Dapatkan:

public IActionResult Create()
{
    ViewData["Tags"] = new SelectList(_context.Tags, "Id", "Name");
    return View();
}

Dalam Posting:

var selectedIds= Request.Form["Tags"];

Dalam penglihatan :

<label>Tags</label>
<select  asp-for="Tags"  id="Tags" name="Tags" class="form-control" asp-items="ViewBag.Tags" multiple></select>
Anas Al-Qudah
sumber