Wählen Sie Tag Helper in ASP.NET Core MVC aus

162

Ich benötige Hilfe beim Auswahl-Tag-Helfer in ASP.NET Core.

Ich habe eine Liste von Mitarbeitern, die ich an einen ausgewählten Tag-Helfer binden möchte. Meine Mitarbeiter sind in einem List<Employee> EmployeesListund ausgewählten Wert wird in EmployeeIdEigentum gehen . Mein Ansichtsmodell sieht folgendermaßen aus:

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

Meine Mitarbeiterklasse sieht folgendermaßen aus:

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

Meine Frage ist, wie ich meinem Select-Tag-Helfer mitteilen kann, dass er Idden Wert als Wert verwenden soll, während er FullNamein der Dropdown-Liste angezeigt wird.

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

Ich würde mich über Hilfe dabei freuen. Vielen Dank.

Sam
quelle
3
Nur etwas, von dem ich dachte, ich sollte es hinzufügen. Es scheint nicht zu funktionieren, wenn Sie das Auswahl-Tag sofort schließen. Schließen Sie die Tags immer mit </ select>. Der Tag-Helfer funktionierte nicht mit <select asp-for ..... />
RoughPlace
Nur ein Tipp. Gerüst-Controller zeigen Ihnen im Allgemeinen die besten Wege zu solchen Dingen
Neville Nazerane

Antworten:

378

Verwenden der Select Tag-Helfer zum Rendern eines SELECT-Elements

Erstellen Sie in Ihrer GET-Aktion ein Objekt Ihres Ansichtsmodells, laden Sie die EmployeeListSammlungseigenschaft und senden Sie diese an die Ansicht.

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);
}

Erstellen Sie in Ihrer Erstellungsansicht ein neues SelectListObjekt aus der EmployeeListEigenschaft und übergeben Sie dieses als Wert für die asp-itemsEigenschaft.

@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>

Und Ihre HttpPost-Aktionsmethode zum Akzeptieren der übermittelten Formulardaten.

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

Oder

Wenn Ihr Ansichtsmodell eine List<SelectListItem>Eigenschaft als Eigenschaft für Ihre Dropdown-Elemente hat.

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

Und in Ihrer Aktion,

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);
}

Und in der Ansicht können Sie die EmployeesEigenschaft direkt für die verwenden 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>

Die Klasse SelectListItemgehört zum Microsoft.AspNet.Mvc.RenderingNamespace.

Stellen Sie sicher, dass Sie ein explizites schließendes Tag für das Auswahlelement verwenden. Wenn Sie den selbstschließenden Tag-Ansatz verwenden, rendert der Tag-Helfer ein leeres SELECT-Element!

Der folgende Ansatz funktioniert nicht

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

Aber das wird funktionieren.

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

Abrufen von Daten aus Ihrer Datenbanktabelle mithilfe des Entity Framework

In den obigen Beispielen werden fest codierte Elemente für die Optionen verwendet. Also dachte ich, ich werde einen Beispielcode hinzufügen, um Daten mit dem Entity Framework zu erhalten, da viele Leute das verwenden.

Nehmen wir an, Ihr DbContext-Objekt hat eine Eigenschaft namens Employees, die vom Typ ist, DbSet<Employee>in dem die EmployeeEntitätsklasse eine Idund -Eigenschaft Namewie diese hat

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

Sie können eine LINQ-Abfrage verwenden, um die Mitarbeiter abzurufen, und die Select-Methode in Ihrem LINQ-Ausdruck verwenden, um eine Liste von SelectListItemObjekten für jeden Mitarbeiter zu erstellen .

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);
}

Angenommen, es contexthandelt sich um Ihr Datenbankkontextobjekt. Der Ansichtscode ist der gleiche wie oben.

Verwenden von SelectList

Einige Leute bevorzugen es, die SelectListKlasse zu verwenden, um die Elemente zu speichern, die zum Rendern der Optionen erforderlich sind.

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

Jetzt können Sie in Ihrer GET-Aktion den SelectListKonstruktor verwenden, um die EmployeesEigenschaft des Ansichtsmodells zu füllen. Stellen Sie sicher, dass Sie die Parameter dataValueFieldund dataTextFieldangeben.

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" }
    };
}

Hier rufe ich die GetEmployeesMethode auf, um eine Liste der Mitarbeiterobjekte mit jeweils einer Idund FirstName-Eigenschaft abzurufen, und verwende diese Eigenschaften als DataValueFieldund DataTextFieldfür das von SelectListuns erstellte Objekt. Sie können die fest codierte Liste in einen Code ändern, der Daten aus einer Datenbanktabelle liest.

Der Ansichtscode ist derselbe.

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

Rendern Sie ein SELECT-Element aus einer Liste von Zeichenfolgen.

Manchmal möchten Sie möglicherweise ein ausgewähltes Element aus einer Liste von Zeichenfolgen rendern. In diesem Fall können Sie den SelectListKonstruktor verwenden, der nur benötigtIEnumerable<T>

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

Der Ansichtscode ist derselbe.

Ausgewählte Optionen einstellen

Manchmal möchten Sie möglicherweise eine Option als Standardoption im SELECT-Element festlegen (z. B. möchten Sie in einem Bearbeitungsbildschirm den zuvor gespeicherten Optionswert laden). Dazu können Sie den EmployeeIdEigenschaftswert einfach auf den Wert der Option setzen, die Sie auswählen möchten.

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);
}

Dadurch wird die Option Tom im Auswahlelement ausgewählt, wenn die Seite gerendert wird.

Dropdown-Liste mit Mehrfachauswahl

Wenn Sie ein Dropdown-Menü mit Mehrfachauswahl rendern möchten, können Sie einfach die Eigenschaft Ihres Ansichtsmodells, die Sie für das asp-forAttribut in Ihrer Ansicht verwenden, in einen Array-Typ ändern .

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

Dadurch wird das HTML-Markup für das Auswahlelement mit dem multipleAttribut gerendert, mit dem der Benutzer mehrere Optionen auswählen kann.

@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>

Ausgewählte Optionen in Mehrfachauswahl einstellen

Setzen Sie den EmployeeIdsEigenschaftswert ähnlich wie bei der Einzelauswahl auf ein Array von Werten, die Sie möchten.

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);
}

Dadurch wird die Option Tom und Jerry im Mehrfachauswahlelement ausgewählt, wenn die Seite gerendert wird.

Verwenden von ViewBag zum Übertragen der Liste der Elemente

Wenn Sie es nicht vorziehen, eine Sammlungstyp-Eigenschaft beizubehalten, um die Liste der Optionen an die Ansicht zu übergeben, können Sie dies mit dem dynamischen ViewBag tun. ( Dies ist nicht mein persönlich empfohlener Ansatz, da viewbag dynamisch ist und Ihr Code nicht abgefangen werden kann Tippfehler )

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

und in der Ansicht

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

Verwenden von ViewBag zum Übertragen der Liste der Elemente und Festlegen der ausgewählten Option

Es ist das gleiche wie oben. Alles, was Sie tun müssen, ist, den Wert der Eigenschaft (für die Sie das Dropdown-Menü binden) auf den Wert der Option festzulegen, die Sie auswählen möchten.

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());
}

und in der Ansicht

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

Elemente gruppieren

Die Select-Tag-Hilfsmethode unterstützt Gruppierungsoptionen in einer Dropdown-Liste. Sie müssen lediglich den GroupEigenschaftswert der einzelnen SelectListItemElemente in Ihrer Aktionsmethode angeben .

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);
}

Der Ansichtscode wird nicht geändert. Der Select-Tag-Helfer rendert nun die Optionen in 2 Optgruppenelementen .

Shyju
quelle
1
Danke dir! Ein bisschen wie die alte Rasierersyntax, bei der wir eine Konvertierung in SelectList durchführen müssen. Danke noch einmal.
Sam
7
Ich suchte nach einer Möglichkeit, eine leere Option hinzuzufügen, danke für die Verwendung von<option>Please select one</option>
Serj Sagan
5
Beachten Sie, dass Sie ein schließendes </ select> -Tag haben MÜSSEN. Dies funktioniert nicht, wenn Sie versuchen, das select-Tag wie <select ... /> selbst zu schließen. Wenn Sie eine leere Option wie "Bitte wählen Sie eine aus" verwenden, müssen Sie ihr den Wert "leere Zeichenfolge" "geben, damit die erforderliche Feldvalidierung funktioniert.
Andy
3
"Stellen Sie sicher, dass Sie ein explizites schließendes Tag für das Auswahlelement verwenden. Wenn Sie den Ansatz des selbstschließenden Tags verwenden, rendert der Tag-Helfer ein leeres SELECT-Element!" Dies war das Problem in meinem Fall. Prost!
Mariusz
2
Vielen Dank, dass Sie sich so viel Mühe gegeben haben!
Vidar
11

Ich habe dafür eine Schnittstelle und einen <options>Tag-Helfer erstellt. Ich musste die IEnumerable<T>Elemente also nicht IEnumerable<SelectListItem>jedes Mal konvertieren , wenn ich das <select>Steuerelement füllen musste.

Und ich denke es funktioniert wunderbar ...

Die Verwendung ist so etwas wie:

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

Und damit es mit dem Tag-Helfer funktioniert, müssen Sie diese Schnittstelle in Ihrer Klasse implementieren:

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

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

Dies sind die benötigten Codes:

Die Schnittstelle:

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

Der <options>Tag-Helfer:

[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>");
            }
        }
    }
}

Es mag Tippfehler geben, aber das Ziel ist klar, denke ich. Ich musste ein bisschen bearbeiten.

Yves
quelle
4

Sie können auch IHtmlHelper.GetEnumSelectList verwenden.

    // 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
quelle
3

Meine Antwort unten nicht lösen die Frage , sondern es bezieht sich auf.

Wenn jemand enumanstelle eines Klassenmodells Folgendes verwendet:

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

Und eine Eigenschaft, um den Wert beim Einreichen zu erhalten:

public int No { get; set; }

Auf der Rasierseite können Sie Html.GetEnumSelectList<Counter>()die Aufzählungseigenschaften abrufen.

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

Es generiert den folgenden HTML-Code:

<select id="No" name="No">
    <option value="1">Number 1</option>
    <option value="2">Number 2</option>
    <option value="3">Number 3</option>
</select>
Bräunen
quelle
3

Sie können den folgenden Code für die Mehrfachauswahl verwenden :

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

Sie können auch verwenden:

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

In Get:

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

In der Post:

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

Im Hinblick auf :

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