dotnet / dotnet/aspnetcore

InputSelect does not bind correctly to Nullable<bool>

Open
#54,565 10 comments 11 reactions 0 assignees View on GitHub
area-blazor bug feature-blazor-builtin-components feature-model-binding
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

### Is there an existing issue for this?

- [X] 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 "/"


What is your favorite color?

Select a Color
Red
Green
Blue


How many legs do you have?

Select a Number
1
2


Are you awesome?

Select Yes or No
Yes
No

Submit

@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: InputSelect
{
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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.