Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Radio Buttons with Individual Labels for Enum using MVC6 Tag Helpers

My model contains an enum which I'm trying to bind to a list of radio buttons, so that only one value can be selected when the form is submitted.

public enum Options
{
    [Display(Name="Option A")
    OptionA,
    [Display(Name="Option B")
    OptionB
}

public class MyModel
{
     public Options SelectedOption {get; set;}
     public string TextA{get; set;}
     public string TextB{get; set;}
}

In MVC 5, I would render a radio button input for each enum value, and the user would be able to select just one. So the code in the view for each radio button would probably look like this:

@Html.RadioButtonFor(m => m.SelectedOption, Options.OptionA)

The problem with MVC6 seems to be that the input tag helper does not support an enum property out of the box. So if I try to add <input asp-for="SelectedOption"/>, all I get is a textbox.

So my question is, is there a way to do this using an MVC6 tag helper (out of the box or custom) or is there another way to do this? Maybe something like using the old razor syntax or just adding an input tag and populating its attributes?

Please note that ideally there have to be labels for both radio buttons showing the text specified in the enum's [Display] attributes. Also, only one of the TextA or TextB textboxes can appear at the same time and this should be based on the selected radio button, but this is out of the scope of the question. So here's how the rendered markup should look like (more or less):

<div>
    <div>
        <input id="OptionA" type="radio" name="SelectedOption"/>
        <label for="OptionA">Option A</label>
    </div>
    <div>
        <label for="TextA">Text A</label>
        <input type="text" id="TextA" name="TextA">
    </div>
<div>

<div>
<div>
    <input id="OptionB" type="radio" name="SelectedOption"/>
    <label for="OptionB">Option B</label>
</div>

    <div>
        <label for="TextB">Text A</label>
        <input type="text" id="TextB" name="TextB">
    </div>
<div>
like image 973
elolos Avatar asked Nov 12 '15 20:11

elolos


People also ask

Is there a tag helper for radio buttons in MVC 6?

I don't see any tag helpers for radio buttons in ASP.NET 5 MVC 6. What's the right way of handling form elements where I need to use radio buttons? Show activity on this post. There is a TagHelper for all the input types which includes the radio button type as well. Assuming you have a view model like this

How to create a radio button element in MVC using HTML?

RadioButtonFor (). The Html.RadioButton () HTML Helper method in ASP.NET MVC Application is used to create a radio button element with a specified name, isChecked boolean property, and the HTML attributes. The Html.RadioButton () HTML Helper method is a loosely type method.

Can I use HTML helper radio-button in model?

This HTML Helper radio-button is not attached / bound with any Model. You can directly use HTML element of a Radio button. Just follow the below images to see how to work around these.

What is radiobutton in mvchtmlstring?

The Html.RadioButton () method creates an radio button element with a specified name, isChecked boolean and html attributes. MvcHtmlString RadioButton (string name, object value, bool isChecked, object htmlAttributes) Please visit MSDN to know all the overloads of RadioButton () method.


1 Answers

<enum-radio-button asp-for="ThisEnum"></enum-radio-button>
<enum-radio-button asp-for="ThisEnum" value="ThisEnum.Value001"></enum-radio-button>

ThisEnum.Value001 = Auto Checked radio input..

Asp.Net Core TagHelper for enum radio button list

/// <summary>
/// <see cref="ITagHelper"/> implementation targeting &lt;enum-radio-button&gt; elements with an <c>asp-for</c> attribute, <c>value</c> attribute.
/// </summary>
[HtmlTargetElement("enum-radio-button", Attributes = RadioButtonEnumForAttributeName)]
public class RadioButtonEnumTagHelper : TagHelper
{
    private const string RadioButtonEnumForAttributeName = "asp-for";
    private const string RadioButtonEnumValueAttributeName = "value";

    /// <summary>
    /// Creates a new <see cref="RadioButtonEnumTagHelper"/>.
    /// </summary>
    /// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
    public RadioButtonEnumTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }

    /// <inheritdoc />
    public override int Order => -1000;

    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }

    protected IHtmlGenerator Generator { get; }

    /// <summary>
    /// An expression to be evaluated against the current model.
    /// </summary>
    [HtmlAttributeName(RadioButtonEnumForAttributeName)]
    public ModelExpression For { get; set; }

    [HtmlAttributeName(RadioButtonEnumValueAttributeName)]
    public Enum value { get; set; }

    /// <inheritdoc />
    /// <remarks>Does nothing if <see cref="For"/> is <c>null</c>.</remarks>
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {

        var childContent = await output.GetChildContentAsync();
        string innerContent = childContent.GetContent();
        output.Content.AppendHtml(innerContent);

        output.TagName = "div";
        output.TagMode = TagMode.StartTagAndEndTag;
        output.Attributes.Add("class", "btn-group btn-group-radio");

        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (output == null)
        {
            throw new ArgumentNullException(nameof(output));
        }

        var modelExplorer = For.ModelExplorer;
        var metaData = For.Metadata;

        if (metaData.EnumNamesAndValues != null)
        {
            foreach (var item in metaData.EnumNamesAndValues)
            {
                string enum_id = $"{metaData.ContainerType.Name}_{metaData.PropertyName}_{item.Key}";

                bool enum_ischecked = false;
                if (value != null)
                {
                    if (value != null && item.Key.ToString() == value.ToString())
                    {
                        enum_ischecked = true;
                    }
                }
                else
                {
                    if (For.Model != null && item.Key.ToString() == For.Model.ToString())
                    {
                        enum_ischecked = true;
                    }
                }

                string enum_input_label_name = item.Key;
                var enum_resourced_name = metaData.EnumGroupedDisplayNamesAndValues.Where(x => x.Value == item.Value).FirstOrDefault();
                if (enum_resourced_name.Value != null)
                {
                    enum_input_label_name = enum_resourced_name.Key.Name;
                }

                var enum_radio = Generator.GenerateRadioButton(
                    ViewContext,
                    For.ModelExplorer,
                    metaData.PropertyName,
                    item.Key,
                    false,
                    htmlAttributes: new { @id = enum_id });
                enum_radio.Attributes.Remove("checked");
                if (enum_ischecked)
                {
                    enum_radio.MergeAttribute("checked", "checked");
                }
                output.Content.AppendHtml(enum_radio);

                var enum_label = Generator.GenerateLabel(
                    ViewContext,
                    For.ModelExplorer,
                    For.Name,
                    enum_input_label_name,
                    htmlAttributes: new { @for = enum_id, @Class = "btn btn-default" });
                output.Content.AppendHtml(enum_label);
            }
        }
    }
}

I'm using this style

Html result

like image 142
dizaynplus Avatar answered Jan 02 '23 12:01

dizaynplus