In this article, we are going to learn about the select tag helper and its various uses.
We are going to start with a brief overview of what exactly tag helpers in ASP.NET Core are and then proceed to learn more about the select tag helper.
Let’s begin.
Tag Helpers in ASP.NET Core
Tag helpers enable server-side code to participate in creating and rendering HTML elements in Razor files.
In simpler terms, a tag helper is a server-side component that helps create and render HTML elements in Razor files.
ASP.NET Core provides a variety of built-in tag helpers that are very helpful in creating Razor views and pages.
But before we tackle select tag helper let’s clear one more thing up.
Tag Helpers vs HTML Helpers
Both tag helpers and HTML helpers render HTML elements in Razor files, however, they have their syntactical differences.
Let’s first generate a strongly typed input
element using an HTML helper:
<div class="form-group"> <label for="city">City with HTML Helper</label> @Html.TextBoxFor(m => m.City, new {@class="form-control"}) @Html.ValidationMessageFor(m => m.City, message:"City can't be empty", new {@class="text-danger font-weight-bold"}) </div>
Now, we use an input
tag helper to generate the same markup:
<div class="form-group"> <label for="city">City with Tag Helper</label> <input type="text" class="form-control" asp-for="City"> <span asp-validation-for="City" class="text-danger font-weight-bold"></span> </div>
Tag helpers provide a more native HTML kind of feel while creating web pages whereas HTML helpers are invoked similarly to methods that are mixed with HTML inside Razor views.
The result is the same, but the syntax is different.
Now that we are aware of tag helpers, let’s learn about the select
tag helper in detail.
Select Tag Helper
select
tag helper generates a select
element and the associated option
elements for the properties of a model.
In simpler terms, it helps to generate a dropdown list for a given model.
We have two very important attributes for a select
tag helper:
asp-for
: It specifies the model property name for theselect
elementasp-items
: It specifies theoption
items
The HTML helper counterpart of a select
tag helper is Html.DropDownListFor(x=> x.PropertyName)
.
Use a List<SelectListItem> to Render a Select Element
Let’s create a ProductViewModel
with a string
and a List<SelectListItem>
properties:
public class ProductViewModel { public string Product { get; set; } public List<SelectListItem> Products { get; set; } }
After that, we create an MVC action method to return a view with an instance of the ProductViewModel
:
public IActionResult Index() { var model = new ProductViewModel { Products = new List<SelectListItem> { new SelectListItem { Text = "Motherboards", Value = "MB" }, new SelectListItem { Text = "Graphic Cards", Value = "GC" }, new SelectListItem { Text = "Liquid Coolants", Value = "LC" } }, Product = "GC" }; return View(model); }
Finally, we work on the Index
view and render a dropdown list with the help of a select
tag helper:
@model ProductViewModel @{ ViewData["Title"] = "Home Page"; } <h3>Products Dropdown List</h3> <form method="post"> <select class="form-select-sm" asp-for="Product" asp-items="@Model.Products"></select> <div class="mt-4"> <input class="btn btn-primary" type="submit" value="Submit"/> </div> </form>
The asp-for
attribute is bound to the string Product
property while the asp-items
attribute is bound to the list of SelectListItems
.
SelectListItem
is a class that resides in Microsoft.AspNetCore.Mvc.Rendering
namespace.
Let’s debug the project and browse the Index view:
Graphic Cards is by default selected in the dropdown because we have set Product = "GC"
in the code.
We can inspect the dropdown element to find further details:
asp-for="Product"
renders both the id
and name
attributes as Product
, the name
attribute helps in sending the selected dropdown value to the POST action method when we submit the form.
Now, we can create a post-action method:
[HttpPost] public IActionResult Index(ProductViewModel model) { var selectedProduct = model.Product; return Content("The selected value: " + selectedProduct); }
The selected
value of the products dropdown transfers from the view to the controller via the Product
property.
Now that we have seen the usage of SelectListItem
, let’s explore how we can render a select
tag helper using different mechanisms.
Use a List<ComplexViewModel> to Render a Select Element
Let’s create an EmployeeViewModel
with an Id
and EmployeeName
properties:
public class EmployeeViewModel { public int Id { get; set; } public string EmployeeName { get; set; } }
We can create a static method to return a few dummy entries:
public static List<EmployeeViewModel> GetEmployees() { return new List<EmployeeViewModel> { new EmployeeViewModel { Id = 101, EmployeeName = "Mark" }, new EmployeeViewModel { Id = 102, EmployeeName = "Dave" }, new EmployeeViewModel { Id = 103, EmployeeName = "Rosy" } }; }
Now, we create an action method to return a view with these dummy employees:
public IActionResult SelectTagHelperWithComplexViewModel() { var model = new SelectViewModel { Employees = StaticRepository.GetEmployees() }; return View(model); }
And a dropdown list using the select
tag helper:
@model SelectViewModel @{ ViewData["Title"] = "Employee Dropdown"; } <h3 class="mt-2">Employees Dropdown - Using a List of Complex Models</h3> <select class="form-select-sm" asp-for="SelectedEmployeeId" asp-items="new SelectList(@Model.Employees, nameof(EmployeeViewModel.Id), nameof(EmployeeViewModel.EmployeeName))"> <option>Please Select</option> </select>
In this case, we can’t directly use the @Model.Employees
property with the asp-items
attribute, because we are using a complex class EmployeeViewModel
.
We need to tweak the approach and create a SelectList
object on the fly:
public SelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue);
Use a Static List to Render a Select Element
Let’s create a list of countries:
public static List<string> GetCountries() { return new List<string> { "India","USA","UK","France","Germany" }; }
After that, we create an action method to return a view with the countries list:
public IActionResult SelectTagHelperWithListOfStrings() { var model = new SelectViewModel { Countries = new SelectList(StaticRepository.GetCountries()) }; return View(model);
And render a countries dropdown with the help of a select
tag helper:
@model SelectViewModel @{ ViewData["Title"] = "Countries dropdown"; } <h3 class="mt-2">Countries Dropdown - Using a List of static strings</h3> <select class="form-select-sm" asp-for="SelectedCountry" asp-items="@Model.Countries"> <option>Please Select</option> </select>
We are able to equate the asp-items
directly to @Model.Countries
because the Countries
property is a SelectList
.
Use an Enum to Render a Select Element
Let’s create a Department enum
:
public enum Department { IT, HR, Finance, Admin }
Now, we can create an enum
type property in a view model:
public class SampleViewModel { public Department Department { get; set; } }
After that, we can create an action method to return a view with the SampleViewModel
:
public IActionResult SelectTagHelperWithEnum() { var model = new SampleViewModel(); return View(model); }
Finally, we create the view and render the select
element using the enum
:
@model SampleViewModel @{ ViewData["Title"] = "Department dropdown"; } <h3 class="mt-2">Department Dropdown - Using an enum</h3> <select class="form-select-sm" asp-for="Department" asp-items="@Html.GetEnumSelectList<Department>()"> <option>Please Select</option> </select>
We are using @Html.GetEnumSelectList<T>()
method to tie the asp-items
when using enums
.
Get the Selected Value of the Select Element in the Post Action Method
The model property tied to the asp-for
attribute is responsible for getting the selected value of the select element:
public IActionResult Details() { var model = new SelectViewModel { Genders = StaticRepository.GetGenders(), Employees = StaticRepository.GetEmployees(), Countries = new SelectList(StaticRepository.GetCountries()) }; return View(model); } [HttpPost] public IActionResult Details(SelectViewModel model) { var selectedGender = model.SelectedGender; var selectedEmployee = model.SelectedEmployeeId; var selectedCountry = model.SelectedCountry; var selectedDepartment = model.SelectedDepartment; return RedirectToAction("Details"); }
Let’s debug the application and submit the Details form:
All the selected properties get populated correctly.
How to Set a Default Value in the Select Element
In the GET action method, we need to set the properties that will be tied with the asp-for
attribute.
We can tweak the GET action and explicitly set the individual properties:
public IActionResult Details() { var model = new SelectViewModel { Genders = StaticRepository.GetGenders(), Employees = StaticRepository.GetEmployees(), Countries = new SelectList(StaticRepository.GetCountries()), SelectedGender = "Female", SelectedEmployeeId = 102, SelectedCountry = "USA", SelectedDepartment = 2 }; return View(model); }
Now, we can run the project and browse the view:
We see that all 4 dropdowns have a default option selected.
Render a Multi-Select Dropdown
We will be using the multiple
attribute of the select
tag helper to achieve this functionality.
Let’s create a separate view model and house the required properties:
public class MultiSelectViewModel { public List<EmployeeViewModel> Employees { get; set; } public int[] SelectedEmployeeIds { get; set; } }
The Employees
property populates the option
elements, while the SelectedEmployeeIds
property that is an integer
array will help to send multiple selected values to the post-action method when we submit the form.
Now, we can create the view:
@model MultiSelectViewModel @{ ViewData["Title"] = "Multi Select Dropdown"; } <h3>Multi Select Dropdown</h3> <form method="post"> <div> <select class="form-select multi-select-dropdown" asp-for="SelectedEmployeeIds" multiple asp-items="new SelectList(@Model.Employees, nameof(EmployeeViewModel.Id), nameof(EmployeeViewModel.EmployeeName))"> </select> </div> <div class="mt-4"> <input type="submit" value="Submit" class="btn btn-primary" /> </div> </form>
After that, we run the application and browse the view:
Finally, we can create a POST action method and submit the form to get multiple selected values from the dropdown:
We get Mark’s and Dave’s employee ids in the SelectedEmployeeIds
array when we submit the form.
Grouping Items in a Select Element
At times, we get the requirement to group option
elements under some common classification in a dropdown.
SelectListItem
class has a Group
property that helps to group multiple options with the same group names under one classification.
We can create a method that will use the Group
property and return a list of SelectListItem
:
public static List<SelectListItem> GetCourses(SelectListGroup science, SelectListGroup humanities) { return new List<SelectListItem> { new SelectListItem { Text = "Physics", Value = "PH101", Group = science }, new SelectListItem { Text = "Chemistry", Value = "CH101", Group = science }, new SelectListItem { Text = "Mathematics", Value = "MT101", Group = science }, new SelectListItem { Text = "English", Value = "EN101", Group = humanities }, new SelectListItem { Text = "Environmental Studies", Value = "EN101", Group = humanities }, new SelectListItem { Text = "Economics", Value = "EC101", Group = humanities } }; }
We have two groups – science and humanities. These groups have been assigned to the separate SelectListItem
instances.
Now, we can create the action method:
public IActionResult Grouped() { var sciences = new SelectListGroup { Name = "Science" }; var humanities = new SelectListGroup { Name = "Humanities" }; var model = new GroupViewModel { Courses = StaticRepository.GetCourses(sciences, humanities) }; return View(model); }
We create two SelectListGroup
, assign the names “Science” and “Humanities” and call the StaticRepository.GetCourses()
method.
Let’s create the select
tag helper that demonstrates the grouped functionality:
@model GroupViewModel @{ ViewData["Title"] = "Grouped Dropdown"; } <h3>Grouped drodown list</h3> <select class="form-select-sm" asp-items="@Model.Courses"> <option>Please Select</option> </select>
Finally, we run the application and browse the view:
The option
elements are divided into Science and Humanities groups respectively.
Conclusion
In this article, we have learned about tag helpers, and how are they different from HTML helpers. We have learned in detail about the select tag helper, and the various ways we can render the select element.