David Masters
David Masters

Reputation: 8295

Blazor Server Side race condition with form fields

I have an issue where a radio button selection is reset immediately after clicking it.

I have the following fields in a form:

enter image description here

I think what's happening is:

  1. The user types a value into the input
  2. The user then clicks a radio option (whilst having focus in the text input)
  3. This click triggers the onChange/bind event for the text input to fire server side
  4. For a brief moment, the user see's their radio option selected
  5. 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>&nbsp;</text>@option.Name<br>
    }
</InputRadioGroup>

How do you prevent this?

Upvotes: 0

Views: 558

Answers (2)

David Masters
David Masters

Reputation: 8295

It turned out that there is an issue with the InputRadioGroup control.

This GitHub issue describes the problem.

Basically, it will always rebuild its internals (So in your case the InputRadio components) due to an always-changing Key, resulting in the same kind of race condition as above.

The suggested workaround (which worked) is to implement a custom InputRadioGroup with the following added behaviour:

 public class MyInputRadioGroup<TValue> : InputRadioGroup<TValue>
 {
     private string? _name;
     private string? _fieldClass;

     protected override void OnParametersSet()
     {
         var fieldClass = EditContext?.FieldCssClass(FieldIdentifier) ?? string.Empty;
         if (fieldClass != _fieldClass || Name != _name)
         {
             _fieldClass = fieldClass;
             _name = Name;
             base.OnParametersSet();
         }
     }
 }

I believe this will be addressed in .NET 7 as per this pull request

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273179

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

Upvotes: 1

Related Questions