RadioGroup
An interactive page: C# runs over a Blazor Server connection.
Usage
@* An enum: its values are the options, named by their [Display(Name)]. *@
<RadioGroup @bind-Value="Model!.Digest" />
@* Other values, with ItemText for each one's text. *@
<RadioGroup @bind-Value="Model!.Rate" Items="Rates.Keys" ItemText="RateText"
Orientation="Orientation.Horizontal" />For two to five short options, a SegmentedControl takes less room; for a long list, use a Select.
Stacked or in a row
Use Orientation.Horizontal to put a few short options in a row, wrapping when there isn't room; they stack by default. An enum's values are the options, named by their [Display(Name)].
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="radio-group-horizontal" MaxWidth="28.Rem" Grow>
<RadioGroup @bind-Value="Model!.Digest" Hint="A summary of your projects' activity, by email." />
<RadioGroup @bind-Value="Model!.Contact" Orientation="Orientation.Horizontal" />
</Form>
{
[SupplyParameterFromForm(FormName = "radio-group-horizontal")]
private Preferences? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
public sealed class Preferences
{
[Display(Name = "Email digest")]
public Digest Digest { get; set; } = Digest.Weekly;
[Display(Name = "Preferred contact")]
public ContactMethod Contact { get; set; } = ContactMethod.Email;
}
public enum Digest { Daily, Weekly, Never }
public enum ContactMethod
{
Email,
Phone,
[Display(Name = "Don't contact me")] None,
}
}Options from a list
Use Items for options that aren't an enum, and ItemText for how each one reads.
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="radio-group-shipping" MaxWidth="24.Rem" Grow>
<RadioGroup @bind-Value="Model!.Rate" Items="Rates.Keys" ItemText="RateText" />
</Form>
{
[SupplyParameterFromForm(FormName = "radio-group-shipping")]
private Checkout? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private static readonly Dictionary<string, (string Name, decimal Price)> Rates = new()
{
["standard"] = ("Standard, 3 to 5 days", 4.99m),
["express"] = ("Express, 1 to 2 days", 12.99m),
["pickup"] = ("Pick up in store", 0m),
};
private static string RateText(string? key)
{
var (name, price) = Rates[key!];
return price == 0 ? $"{name}: free" : $"{name}: ${price}";
}
public sealed class Checkout
{
[Display(Name = "Shipping")]
public string? Rate { get; set; } = "standard";
}
}Each radio posts its value as text and Blazor turns it back into the property's type, so use values that do that, such as strings, numbers or enums. A post can carry a value that isn't among the options, and it reaches the model, so check it on the server.
Required, with nothing chosen
Bind a nullable property with [Required] to start with nothing chosen and need a choice.
Preview
Code
System.ComponentModel.DataAnnotations
<Form Model="Model" FormName="radio-group-required-choice" OnValidSubmit="Save" MaxWidth="28.Rem" Grow>
<RadioGroup @bind-Value="Model!.Source" />
<Row><Button Submit>Send</Button></Row>
if (_sent is not null)
{
<Alert Status="Status.Success">Thanks: you heard about us from _sent.</Alert>
}
else if (_unknown)
{
<Alert Status="Status.Danger">Choose one of the options.</Alert>
}
</Form>
{
[SupplyParameterFromForm(FormName = "radio-group-required-choice")]
private Survey? Model { get; set; }
private string? _sent;
private bool _unknown;
protected override void OnInitialized() => Model ??= new();
// What was sent, not the field: on an interactive page it changes as people choose. A post
// can carry any number for an enum, so anything else is turned away.
private void Save()
{
_sent = Model!.Source switch
{
Source.Friend => "a friend or colleague",
Source.Search => "a search",
Source.Social => "social media",
Source.Talk => "a talk",
_ => null,
};
_unknown = _sent is null;
}
public sealed class Survey
{
// Nullable, so nothing is chosen until someone chooses.
[Required(ErrorMessage = "Choose how you heard about us")]
[Display(Name = "How did you hear about us?")]
public Source? Source { get; set; }
}
public enum Source
{
[Display(Name = "A friend or colleague")] Friend,
Search,
[Display(Name = "Social media")] Social,
[Display(Name = "A conference talk")] Talk,
}
}Live: The browser stops the post in the model's words, as on static pages, and Send runs C# without a page load.
A property that isn't nullable always has a value, so [Required] never fails: the option for its starting value (an enum's 0, unless the model sets another) is chosen from the start. The example also turns away a posted number that isn't one of the enum's values.
Sizes and disabled
Use Size to line up with buttons and other fields, and Disabled for a choice that can't change, which doesn't post. There's no ReadOnly: HTML has no read-only radio, and in a read-only Form the group is disabled while a hidden field posts its value.
Preview
Code
<Form Model="Model" FormName="radio-group-states" MaxWidth="32.Rem" Grow>
<RadioGroup @bind-Value="Model!.Small" Label="Small" Size="ControlSize.Sm" Orientation="Orientation.Horizontal" />
<RadioGroup @bind-Value="Model!.Large" Label="Large" Size="ControlSize.Lg" Orientation="Orientation.Horizontal" />
<RadioGroup @bind-Value="Model!.Region" Label="Region" Disabled Orientation="Orientation.Horizontal"
Hint="Disabled: not posted." />
</Form>
{
[SupplyParameterFromForm(FormName = "radio-group-states")]
private Account? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
public sealed class Account
{
public Priority Small { get; set; } = Priority.Normal;
public Priority Large { get; set; } = Priority.Normal;
public Region Region { get; set; } = Region.Europe;
}
public enum Priority { Low, Normal, High }
public enum Region { Americas, Europe, Asia }
}A disabled field posts nothing, so after a static post its property holds its default (an enum's 0, or null): keep its value on the server rather than saving it from the post.
Mode support
| Feature | Off | Static | Live |
|---|---|---|---|
| Everything | Yes | Yes | Yes |
Off: JavaScript disabled. Static: a static SSR page with IzzyBlazor's script. Live: an interactive page (Server, WebAssembly or Auto).
Accessibility
- It renders native radio buttons in a
fieldsetwhoselegendis the label, so Tab reaches the group and the arrow keys move the choice. - Each option's text is its
label; the hint and errors are linked to the group witharia-describedby, and each radio setsaria-invalidwhen the field is invalid. - After a post that fails with an error here, the checked radio (or the first) takes focus, so screen readers read the group's name and error (its description); a
FormErrorsearlier in the page takes it first. Not on interactive pages: there, use aFormErrors.
Parameters
| Prop | Type | Default |
|---|---|---|
ItemsThe options. | IEnumerable<TValue>? | |
ItemTextThe text for each option. | Func<TValue, string>? | computed |
OrientationStack options vertically (the default) or in a row. | Orientation | Orientation.Vertical |
@bind-ValueThe value, bound with @bind-Value. | TValue | |
DisplayNameThe field's name in validation messages from the input itself, such as a value that can't be parsed. | string? |
Plus 26 field props.
Full APISee also
- SegmentedControl: one choice from a few, as joined buttons.
- Select: a native select, themed where the browser allows.
- CheckboxGroup: several choices as checkboxes.