Mvc: Tag helper to render checkbox/radio button list for Enum (incl. flags)

Created on 27 Jul 2016  路  17Comments  路  Source: aspnet/Mvc

Do taghelpers currently supports the following scenarios?
I have a feeling that this is currently supported but I'm missing something.
I'm not sure how to use taghelpers in this cases.

_Scenario1:_ radio

enum Gender {
    Male,
    Female
}

ViewModel {
    Gender Gender {get;set;}
}

so I get multiple (two in this case) radio buttons (one for Male and one for Female).
desired html output (doesn't have to be exact):

<label>
    <input type="radio" name="Gender" value="0">
    Male
</label>
<label>
    <input type="radio" name="Gender" value="1">
    Female
</label>

and

_Scenario2:_ checkbox

[Flags]
enum Roles {
    Admin,
    User,
    Customer
}

ViewModel {
    Roles Roles {get;set;}
}

so I get multiple (three in this case) checkboxes.

desired html output (doesn't have to be exact):

<label>
    <input type="checkbox" name="Roles" value="0">
    Admin
</label>
<label>
    <input type="checkbox" name="Roles" value="1">
    User
</label>
<label>
    <input type="checkbox" name="Roles" value="2">
    Customer
</label>
enhancement

Most helpful comment

Back to the topic of flags enums...

This flags enum:

``` c#
[Flags]
enum EnumFlag {
First,
Second,
Third
}

Is of course not really a proper flags enum, because the values aren't flags per se. You'd more likely have something like this:

``` c#
[Flags]
enum EnumFlag {
    First = 1 << 0,
    Second = 1 << 1,
    Third = 1 << 2,
}

And now you can combine the flags to create bitmasks. Creating a UI for this flags enum isn't terribly challenging.

But it's quite common for enum types to actually look like this:

c# [Flags] enum EnumFlag { First = 1 << 0, Second = 1 << 1, Third = 1 << 2, All = First | Second | Third, }

And what UI do you generate for that?

And beyond that, how often does one have an enum that needs to be projected in a UI? Apps I've seen are often _data-driven_ when it comes to generating checkbox lists. E.g. "select how you heard about us" has the options "web, friend, family, advertisement, radio, other". Or "pick your top languages" has the options "C#, C, C++, Rust, JavaScript, Go, Other". These are all data-driven - there's no CLR type or enum that describes these - it comes from a database.

I think the problem we often have when trying to project UIs from CLR types is that the CLR types weren't designed to be automatically projected as a UI. All these cases end up making for very complex logic, which creates challenges when it comes to compatibility, and also becomes a bug farm.

Instead, we often create alternatives, which is to just have simpler building blocks, which can then be used in composition to create a UI.

I think I'd rather see an approach where we create smaller building blocks instead of trying to build one-size-fits-all UI projection components.

All 17 comments

What exactly is the scenario? A tag helper to render out the entire radio button list or checkbox list? I don't think we have that. I don't think there was ever an MVC HTML Helper for that either.

One reason we haven't built that helper is that making the UI reasonably customizable is quite challenging... so we just didn't do it 馃槃

Oh guess I'm not missing something then.

The scenario is having validation/metadata passed to the view. (via taghelpers or whatever).
Maybe something like Html.GetEnumSelectList but for checkbox/radios.

I'm not sure (yet) but I think the model binder also has problems with flag enum values. (see * below)
posting: name="Gender" value="Male" checked does not populate the underlying enum on the controller.

checkbox is only used for bool values. While this is fine, I think we are missing a lot of value from the input tag. same for radio.

checkbox/radio are very useful to work with collections and not only booleans.

  • on a side note (i discovered while playing with this)
    Html.GetEnumSelectList doesn't work with flags (where a multiple select will apply perfectly). [not related to this issue tho]
    I think this is because of lack of support for flags enum at the model binder.

I guess this is becoming more of a feature request than anything else.
What do you think?, would it make sense to have this kind of support on the framework?

@Bartmax Html.GetEnumSelectList() is intended for cases like <select asp-for='ListProperty' asp-items='Html.GetEnumSelectList(...)' ... ></select>. But, yes, it has a designed-in restriction around [Flags] enums because such types have no obvious default <option /> collection.

As @Eilon said, we don't have tag helpers that handle generating checkbox or radio button groups. But the <input/> tag helper would generate the radio buttons for your scenario just fine. However a restriction in the <input/> tag helper (it always generates the false case as a type='hidden' field) means that helper is not appropriate for your scenario. This would at least get you the model metadata / validation attributes for the radio buttons.

From my perspective, a tag helper that be used _in_ a checkbox group would be helpful. But new or enhanced HTML helpers seem more appropriate if we start dealing with templates or otherwise generating the entire checkbox / radio button group in a single call. Nice to be able to almost see exactly the generated HTML when looking at a .cshtml file containing tag helpers.

@Bartmax Html.GetEnumSelectList() is intended for cases like