to make an " /> to make an " /> to make an "/>

Inheriting from a tag helper in .NET Core

468 Views Asked by At

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.

1

There are 1 best solutions below

3
Tiny Wang On BEST ANSWER

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>

enter image description here