I'm new to Blazor and just trying my first steps in VS2022 with a client-side WA app.
I do not like the appearance of the built-in <InputRadio>
component. What I want to achieve was a button-styled radio group.
The question:
How can I change the appearance of <InputRadio>
or create something like radio groups myself?
I visited the original source on github (thank you, MicroSoft, for going OS!) and found, that the appearance seems to be built here:
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
Debug.Assert(Context != null);
builder.OpenElement(0, "input");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttributeIfNotNullOrEmpty(2, "class", AttributeUtilities.CombineClassNames(AdditionalAttributes, Context.FieldClass));
builder.AddAttribute(3, "type", "radio");
builder.AddAttribute(4, "name", Context.GroupName);
builder.AddAttribute(5, "value", BindConverter.FormatValue(Value?.ToString()));
builder.AddAttribute(6, "checked", Context.CurrentValue?.Equals(Value));
builder.AddAttribute(7, "onchange", Context.ChangeEventCallback);
builder.CloseElement();
}
My first idea was to inherit from this class and use an own override for BuildRenderTree()
. But the InputRadioContext
needed for Context
is internal
and this looks like a dead end now.
I tried to use buttons within <InputRadioGroup>
, but was not able to deal with the events properly.
Well, the solution is rather trivial for experienced web-developers, but Id like to post an answer in order to help noobs like me :-)
Brian Parker's hint pushed me to this solution, which works fine:
<EditForm Model=@someViewModel>
<InputRadioGroup @[email protected]_via_Id>
@foreach (SomeClass e in someList)
{
<InputRadio class="btn-check" [email protected] [email protected] />
<label class="btn btn-outline-primary" [email protected]>@e.Name</label>
}
</InputRadioGroup>
</EditForm>
Without a <br/>
tag the buttons appear as cloud of chips.
Hint: First I tried to use the object itself in @bind-Value
but found, that the magic binding does not support all types. That's why I added an Id-based binding property to the ViewModel like this:
//the actual property returning an object's instance
public SomeClass TheInstance{ get; set; } = new SomeClass(Guid.NewGuid(), "n.A.");
//helps to magically bind <InputRadio> via Guid-Property
public Guid TheInstance_via_Id
{
//returns the actual object's id
get => TheInstance.Id;
//re-sets the actual object from a shared context store
set => TheInstance= BaseDataContext.ListOfInstances[value];
}