Selecione Tag Helper no ASP.NET Core MVC

Eu preciso de alguma ajuda com o helper tag select no ASP.NET Core.

Eu tenho uma lista de funcionários que estou tentando vincular a um auxiliar de marca de seleção. Meus funcionários estão em uma List EmployeesList e o valor selecionado irá para a propriedade EmployeeId . Meu modelo de visualização é assim:

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

Minha class de funcionário é assim:

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

Minha pergunta é como dizer ao meu ajudante de tag de seleção para usar o Id como o valor ao exibir FullName na lista suspensa?

  

Eu apreciaria alguma ajuda com isso. Obrigado.

   

Usando os helpers Select Tag para renderizar um elemento SELECT em sua view

Em sua ação GET, crie um object de seu modelo de exibição, carregue a propriedade de coleção EmployeeList e envie-a para a exibição.

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

E, em sua visualização de criação, crie um novo object SelectList partir da propriedade EmployeeList e passe-o como valor para a propriedade asp-items .

 @model MyViewModel 

E o seu método de ação HttpPost para aceitar os dados do formulário enviado.

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

Ou

Se seu modelo de exibição tiver uma List como a propriedade de seus itens suspensos.

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

E na sua ação,

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

E na exibição, você pode usar diretamente a propriedade Employees para os asp-items .

 @model MyViewModel 

A class SelectListItem pertence ao namespace Microsoft.AspNet.Mvc.Rendering .

Certifique-se de estar usando uma tag de fechamento explícita para o elemento select. Se você usar a abordagem de tag de fechamento automático, o auxiliar de marcação renderizará um elemento SELECT vazio!

A abordagem abaixo não funcionará

  

Mas isso vai funcionar.

  

Obtendo dados de sua tabela de database usando a estrutura de entidade

Os exemplos acima estão usando itens codificados para as opções. Então eu pensei em adicionar algum código de exemplo para obter dados usando o framework Entity, já que muitas pessoas usam isso.

Vamos supor que seu object DbContext tenha uma propriedade chamada Employees , que é do tipo DbSet que a class de entidade Employee possui uma propriedade Id e Name , como esta.

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

Você pode usar uma consulta linq para obter os funcionários e usar o método Select em sua expressão linq para criar uma lista de objects SelectListItem para cada funcionário.

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

Assumindo que o context é seu object de contexto do database. O código da vista é o mesmo que acima.

Usando SelectList

Algumas pessoas preferem usar a class SelectList para armazenar os itens necessários para processar as opções.

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

Agora, na sua ação GET, você pode usar o construtor SelectList para preencher a propriedade Employees do modelo de exibição. Certifique-se de especificar os parâmetros dataTextField e dataTextField .

 public IActionResult Create() { var vm = new MyViewModel(); vm.Employees = new SelectList(GetEmployees(),"Id","FirstName"); return View(vm); } public IEnumerable GetEmployees() { return new List { new Employee { Id=1, FirstName="Shyju"}, new Employee { Id=2, FirstName="Bryan"} }; } 

Aqui estou chamando o método GetEmployees para obter uma lista de objects Employee, cada um com uma propriedade Id e FirstName e uso essas propriedades como DataValueField e DataTextField do object SelectList que criamos. Você pode alterar a lista codificada para um código que lê dados de uma tabela de database.

O código de visualização será o mesmo.

  

Renderizar um elemento SELECT de uma lista de seqüências de caracteres.

Às vezes você pode querer renderizar um elemento select de uma lista de strings. Nesse caso, você pode usar o construtor SelectList que leva apenas IEnumerable

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

O código de visualização será o mesmo.

Configurando opções selecionadas

Algumas vezes, você pode querer definir uma opção como a opção padrão no elemento SELECT (por exemplo, em uma canvas de edição, você deseja carregar o valor da opção salva anteriormente). Para fazer isso, você pode simplesmente definir o valor da propriedade EmployeeId com o valor da opção que deseja selecionar.

 public IActionResult Create() { var vm = new MyViewModel(); vm.Employees = new List { 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); } 

Isso selecionará a opção Tom no elemento select quando a página for renderizada.

Menu suspenso de seleção múltipla

Se você deseja renderizar um menu suspenso de seleção múltipla, basta alterar a propriedade do modelo de exibição que você usa asp-for atributo asp-for na exibição para um tipo de matriz.

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

Isso renderizará a marcação HTML para o elemento select com o atributo multiple que permitirá ao usuário selecionar várias opções.

 @model MyViewModel  

Definir opções selecionadas em seleção múltipla

Semelhante à seleção única, defina o valor da propriedade EmployeeIds como uma matriz de valores desejada.

 public IActionResult Create() { var vm = new MyViewModel(); vm.Employees = new List { 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); } 

Isso selecionará a opção Tom e Jerry no elemento multi select quando a página for renderizada.

Usando o ViewBag para transferir a lista de itens

Se você não preferir manter uma propriedade de tipo de coleção para passar a lista de opções para a visualização, poderá usar o ViewBag dynamic para fazer isso ( essa não é minha abordagem recomendada, já que viewbag é dynamic e seu código é propenso a ser desfeito). erros de digitação )

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

e na visão

  

Agrupando itens

O método auxiliar de marcação de seleção suporta opções de agrupamento em uma lista suspensa. Tudo o que você precisa fazer é especificar o valor da propriedade Group de cada SelectListItem em seu método de ação.

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

Não há alteração no código de visualização. o auxiliar de marcação de seleção agora renderizará as opções dentro de 2 itens de optgroups .

Eu criei uma interface e um auxiliar de tag para isso. Portanto, não IEnumerable converter os itens IEnumerable em IEnumerable sempre que preciso preencher o controle .

E eu acho que funciona lindamente …

O uso é algo como:

  

E para que funcione com o tag helper você precisa implementar essa interface em sua class:

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

Estes são os códigos necessários:

A interface:

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

O ajudante de tags :

 [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  element a child of a  element the SelectTagHelper targeted? object formDataEntry; context.Items.TryGetValue(typeof(SelectTagHelper), out formDataEntry); var selectedValues = formDataEntry as ICollection; var encodedValues = new HashSet(StringComparer.OrdinalIgnoreCase); if (selectedValues != null && selectedValues.Count != 0) { foreach (var selectedValue in selectedValues) { encodedValues.Add(Generator.Encode(selectedValue)); } } IEnumerable items = null; if (Items != null) { if (Items is IEnumerable) { var enumerable = Items as IEnumerable; if (Items is IEnumerable) items = Items as IEnumerable; else if (Items is IEnumerable) items = ((IEnumerable)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 .", "", "ForAttributeName", nameof(IModelMetadataProvider), "For.Name")); } else { throw new InvalidOperationException("Invalid items for "); } 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($""); else output.Content.AppendHtml($""); } } } } 

Pode haver algum erro de digitação, mas o objective é claro, eu acho. Eu tive que editar um pouco.

Você também pode usar 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 GetEnumSelectList() where TEnum : struct; 

você pode usar o código abaixo para seleção múltipla :

  

você também pode usar:

  

Em Get: // GET: public IActionResult Create () {

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

Em Post: var selectedIds = Request.Form [“Tags”];

Em vista :