I really love the new tag helpers in .NET Core but I want to do something slightly different.
By default you can use <select asp-items="">
to make an old fashioned select list with options.
But I'd like to add a data-image-url
attribute to each option so I can show a picture.
<select>
<option value="1" data-image-url="/picture.jpg">First Option</option>
<option value="2" data-image-url="/another-picture.jpg">Second Option</option>
</select>
I created a new class that inherits from SelectListItem
:
public class ProductSelectListItem : SelectListItem
{
public string ImageUrl { get; set; }
}
but I'm having trouble figuring out how to inherit from the standard tag helper class.
Of course I could just put a for loop in the view but I'd like to see if there is a better way.
Is it possible to inherit from the standard Select
tag helper class? An editor template is also an option but I don't know if it is the best/cleanest way to go in .NET Core.
I think we have to use custom taghelper
here. And actually I didn't find a solution to inherit default select
taghelper, so I create a new one.
Related document: create tag helper, the select tag helper.
Firstly, I prepared a new class like SelectListItem
. I copied the code from SelectListItem
but added new properity data_image_url
:
using Microsoft.AspNetCore.Mvc.Rendering;
using static Microsoft.Graph.Constants;
namespace WebAppMvc.Models
{
public class MySelectListItem
{
public MySelectListItem() { }
public MySelectListItem(string text, string value)
: this()
{
Text = text;
Value = value;
}
public MySelectListItem(string text, string value, bool selected)
: this(text, value)
{
Selected = selected;
}
public MySelectListItem(string text, string value, bool selected, bool disabled)
: this(text, value, selected)
{
Disabled = disabled;
}
public MySelectListItem(string text, string value, bool selected, bool disabled, string imgUrl)
: this(text, value, selected, disabled)
{
data_image_url = imgUrl;
}
public bool Disabled { get; set; }
public SelectListGroup Group { get; set; }
public bool Selected { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public string data_image_url { get; set; }
}
}
Then create custom taghelper MselectTagHelper
:
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Net;
using System.Text;
namespace WebAppMvc.Models
{
public class MselectTagHelper : TagHelper
{
public List<MySelectListItem> list { get; set; }
public string aspFor { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "select";
output.Attributes.SetAttribute("id", aspFor);
output.Attributes.SetAttribute("name", aspFor);
var options = "";
if (list != null) {
foreach (var item in list)
{
options += $@"<option value={item.Value} data-image-url={item.data_image_url}>{item.Text}</option>";
}
output.Content.SetHtmlContent(options);
}
}
}
}
Create a viewmodel:
public class CountryViewModel
{
public string Country { get; set; }
public List<MySelectListItem> Countries { get; } = new List<MySelectListItem>
{
new MySelectListItem { Value = "MX", Text = "Mexico", data_image_url="/img.png" },
new MySelectListItem { Value = "CA", Text = "Canada", data_image_url="/img.png" },
new MySelectListItem { Value = "US", Text = "USA", data_image_url="/img.png" },
};
}
Then add @addTagHelper *, projectName
in _ViewImports.cshtml
.
In the view:
@model WebAppMvc.Models.CountryViewModel
<Mselect asp-for="Country" list="Model.Countries"></Mselect>