I have an issue where a radio button selection is reset immediately after clicking it.
I have the following fields in a form:
I think what's happening is:
- The user types a value into the input
- The user then clicks a radio option (whilst having focus in the text input)
- This click triggers the onChange/bind event for the text input to fire server side
- For a brief moment, the user see's their radio option selected
- Presumably when the server responds from the input's onChange event, it re-renders the radio button with the state it received at the time - i.e. no radio selection
Code:
<InputText @bind-Value="_viewModel.Amount"></InputText>
<InputRadioGroup @bind-Value="_viewModel.SelectedOptionId" Name="name">
@foreach (var option in _viewModel.RadioOptions)
{
<InputRadio Name="name" Value="@option.Id.ToString()" />
<text> </text>@option.Name<br>
}
</InputRadioGroup>
How do you prevent this?
CodePudding user response:
What is happening here is that you bind to the wrong type.
I assume that both RadioOption.Id and SelectedOptionId are of type int
.
That is fine, but then don't convert the Options' Ids to something else. It will hinder binding to the Selected value.
<InputRadio Name="name" Value="@option.Id.ToString()" /> -- wrong
<InputRadio Name="name" Value="@option.Id" /> -- ok
CodePudding user response:
The issue is that the click (change
event) is not intercepted by the framework, as the component is being re-rendered once the focus is lost from the input text element, triggering its change
event.
The following technique describes how you handle this:
You simply have to prevent the re-rendering of the component when the input text element lose its focus. To achieve this, you should override the ShouldRender
method like this:
protected override bool ShouldRender()
{
return shouldRender;
}
Define a boolean local variable that should be returned from the ShouldRender
method. When it has the value false, the framework will not re-render even if the state of the component has changed. When it has the value true, the framework will re-render:
private bool shouldRender = false;
Now, we want to prevent the re-rendering of the input type text element... To achieve this you should add the following to it:
@onfocusin="@(() => shouldRender = false)"
Full definition:
<InputText @bind-Value="model.Amount" @onfocusin="@(() => shouldRender = false)"></InputText>
But then we want the radio group to re-render the component as we select a radio button. This can be done by adding:
@onfocusin="@(() => shouldRender = true)"
to the InputRadioGroup
component.
Full definition:
<InputRadioGroup @bind-Value="model.SelectedOption" Name="name" @onfocusin="@(() => shouldRender = true)">
</InputRadioGroup>
Note: The initial rendering of the component must always takes place. That means that the component will always rendered initally, whether the ShouldRender
method returns true or false.
Note: Your model should not contain a list of options. It should contain a single int value pointing to the selected option.