Skip to content

InputSelect does not bind correctly to Nullable<bool> #54565

@petergolde

Description

@petergolde

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

If you create a InputSelect control that is bound (via @bind-Value) to a bool?, it does not work in the same way as InputSelect bound to other nullable types (say int or Enum), and it never displays the null value correctly, but always shows the "false" value.

Expected Behavior

When a Nullable is bound to an InputSelect, the option with value="" should be bound to the null value. This is how other nullable types work with InputSelect, and also is the most useful.

If the model has null, then the option with value="" should be displayed when the form initially shows.

If the select is manually set to the option with value="", then that value should continue to be displayed.

Steps To Reproduce

@page "/"

<EditForm Model="Model" OnValidSubmit="Submit">
    <p>
        <label>What is your favorite color?</label>
        <InputSelect @bind-Value="Model.FavoriteColor">
            <option value="">Select a Color</option>
            <option value="Red">Red</option>
            <option value="Green">Green</option>
            <option value="Blue">Blue</option>
        </InputSelect>
    </p>

    <p>
        <label>How many legs do you have?</label>
        <InputSelect @bind-Value="Model.NumberOfLegs">
            <option value="">Select a Number</option>
            <option value="1">1</option>
            <option value="2">2</option>
        </InputSelect>
    </p>

    <p>
        <label>Are you awesome?</label>
        <InputSelect @bind-Value="Model.Awesome">
            <option value="">Select Yes or No</option>
            <option value="true">Yes</option>
            <option value="false">No</option>
        </InputSelect>
    </p>

    <button>Submit</button>
</EditForm>

@code {
    enum Color { Red, Green, Blue };
    class InputModel
    {
        public Color? FavoriteColor { get; set; } = null;
        public int? NumberOfLegs { get; set; } = null;
        public bool? Awesome { get; set; } = null;
    }

    InputModel Model = new InputModel();

    void Submit()
    { 
        Console.WriteLine($"Color: {Model.FavoriteColor} Legs: {Model.NumberOfLegs} Awesome: {Model.Awesome}");
    }
}

When this form is initially shown, the Favorite Color and Number of Legs selects show the "Select..." option, but the Awesome select shows "No". In addition, any attempt to set the "Awesome" select to "Select Yes or No" has it change immediate back to No.

Exceptions (if any)

No response

.NET Version

8.0.200

Anything else?

I think the fix is to change the src/Components/Web/src/Forms/InputSelect.cs implementation of FormatValueAsString to something like:

        protected override string? FormatValueAsString(TValue? value)
        {
            if (typeof(TValue) == typeof(bool)) {
                return (bool)(object)value! ? "true" : "false";
            }
            else if (typeof(TValue) == typeof(bool?)) {
                if (value == null)
                    return null;
                else 
                    return (bool)(object)value ? "true" : "false";
            }

            return base.FormatValueAsString(value);
        }

Luckily this method is protected, so I can fix this in the meantime by creating my own component:

    public class BetterInputSelect<TValue>: InputSelect<TValue>
    {
        protected override string? FormatValueAsString(TValue? value)
        {
            if (typeof(TValue) == typeof(bool)) {
                return (bool)(object)value! ? "true" : "false";
            }
            else if (typeof(TValue) == typeof(bool?)) {
                if (value == null)
                    return null;
                else 
                    return (bool)(object)value ? "true" : "false";
            }

            return base.FormatValueAsString(value);
        }
    }

But I think the actual InputSelect.cs should be fixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-blazorIncludes: Blazor, Razor ComponentsbugThis issue describes a behavior which is not expected - a bug.feature-blazor-builtin-componentsFeatures related to the built in components we ship or could ship in the futurefeature-model-binding

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions