Using InputRadio with bool values

Viewed 2465

I have an InputRadio control that looks like the following:

<InputRadioGroup Name="FooBar" @bind-Value="Foo.Bar">
    <InputRadio Name="FooBar" Value=1 />Yes<br>
    <InputRadio Name="FooBar" Value=0 />No<br>
</InputRadioGroup>

Foo.Bar is currently a nullable int because it appears that an int is what the built in InputRadio control binding expects. I would rather set Foo.Bar to be a nullable bool instead of an int as my app has a lot of Yes/No questions and working with true/false in the code would make things easier and more readable.

Is there a way in Blazor to configure it so the InputRadio control can bind to a bool value?

3 Answers

First things first, getting a boolean value is usually a checkbox, so you can try that first.

<EditForm Model="@Foo">

    Type: @Foo.Bar.GetType()
    <br />
    Value: @Foo.Bar
    <br /><br />

    <InputCheckbox @bind-Value="@Foo.Bar">I understand</InputCheckbox>

</EditForm>

@code{
    MyClass Foo { get; set; } = new MyClass();

    public class MyClass
    {
        public bool Bar { get; set; } = true;
    }
}

If you do have to use radio buttons, read on.

I think that this should, ideally, work with real bool values but it seems it does not, here is a repro (perhaps you could log it with MS in their repo) - initially it seems to parse OK, but changing the value throws that it can't parse from a string. This indicates to me that they only support string and int for the radio button groups.

<EditForm Model="@Foo">

    Type: @Foo.Bar.GetType()
    <br />
    Value: @Foo.Bar
    <br /><br />

    <InputRadioGroup Name="FooBar" @bind-Value="@Foo.Bar">
        <InputRadio Name="FooBar" Value="@true" />Yes<br>
        <InputRadio Name="FooBar" Value="@false" />No<br>
    </InputRadioGroup>

</EditForm>

@code{
    MyClass Foo { get; set; } = new MyClass();

    public class MyClass
    {
        public bool Bar { get; set; } = true;
    }
}

Solutions:

  • Use an enum if you can (it is basically an integer, which is why it works)
  • Use a helper field that can be parsed to the desired bool value (example below)

For the helper field to work out, you need strings that you can parse and you might need them as variables in the view-model, because just setting Value="@true" or Value="true" will actually either try to look for a field, or use the boolean value, while the HTML element matches as a string. A bit of a catch 22 with the syntax.

<EditForm Model="@Foo">

    Type: @Foo.Bar.GetType()
    <br />
    Value: @Foo.Bar
    <br />
    String Value @Foo.BarString
    <br /><br />

    <InputRadioGroup Name="FooBar" @bind-Value="@Foo.BarString">
        <InputRadio Name="FooBar" Value="@trueVal" />Yes<br>
        <InputRadio Name="FooBar" Value="@falseVal" />No<br>
    </InputRadioGroup>

</EditForm>

@code{
    string trueVal = "true";
    string falseVal = "false";
    MyClass Foo { get; set; } = new MyClass();

    public class MyClass
    {
        public string BarString { get; set; } = "true";
        public bool Bar { get { return bool.Parse(BarString); } set { BarString = value.ToString().ToLowerInvariant(); } }
    }
}

This works in .NET 6:

<InputRadioGroup Name="FooBar" @bind-Value="@Foo.Bar">
    <InputRadio Name="FooBar" Value="@true" />Yes<br>
    <InputRadio Name="FooBar" Value="@false" />No<br>
</InputRadioGroup>

This question is already answered however maybe some people like the solution I present.

Form a InputRadioGroup I expected that you could simply bind it like

<InputRadioGroup Name="FooBar" @bind-Value="@Foo.Bar">
    <InputRadio Name="FooBar" Value="@true" />Yes<br>
    <InputRadio Name="FooBar" Value="@false" />No<br>
</InputRadioGroup>

And that @Foo.Bar would be true or false however this doesn't work. There is a simple work around for this using InputCheckbox and a reversed value.

In your page write

<InputCheckbox @bind-Value="Foo.Bar" type="checkbox" /> Text 1
<InputCheckbox @bind-Value="Foo.ReversedBar" type="checkbox" /> Text 2

And in your Foo model write

    public bool Bar
    {
        get => _bar;
        set
        {
            _bar = value;
            _reversedBar = !value;
        }
    }
    private bool _bar;

    public bool ReversedBar
    {
        get => _reversedBar;
        set
        {
            _reversedBar = value;
            _bar = !value;
        }
    }
    private bool _reversedBar;

Then you could simply store the Foo.Bar value in your database or do whatever you want with it.

If you want that one of the values is already true on page load than you can do that like this.

protected override void OnInitialized()
{
    Foo.Bar = true;
}

If you want the InputCheckbox to be round you can use some css for that.

Related