<MudRadioGroup T="string" SelectedOption="@selectedItem" SelectedOptionChanged="OnSelectedOptionChanged">
@foreach (var item in Items)
{
<div>
<MudRadio Option="@(item)" Color="Color.Primary">@item</MudRadio>
<MudButton OnClick="() => RemoveItem(item)" Variant="Variant.Filled">Remove</MudButton>
</div>
}
</MudRadioGroup>
@code {
private string selectedItem = string.Empty;
private List<string> Items = new()
{
"Item1",
"Item2",
"Item3"
};
private void OnSelectedOptionChanged(string selectedOption)
{
selectedItem = selectedOption;
}
private void RemoveItem(string item)
{
Items.Remove(item);
}
}
I have created a snippet here.
How can I change this so that when items are removed the selected radio is updated in the UI? Currently if I select Item2 and then remove Item1, Item2 and Item3 correctly remain, however Item3 is selected instead of Item2.
It's as if the index is all the MudRadioGroup cares about and it doesn't shift the index to the correct item.
I have tried calling StateHasChanged
at the end of both OnSelectedOptionChanged
and RemoveItem
, but this has no effect.
This issue you're facing can be solved using the @key
attribute.
From Ms Docs
When rendering a list of elements or components and the elements or components subsequently change, Blazor must decide which of the previous elements or components are retained and how model objects should map to them. Normally, this process is automatic and sufficient for general rendering, but there are often cases where controlling the process using the @key directive attribute is required.
We add the @key
to the parent element of the loop item, which in your case is the <div>
.
<MudRadioGroup T="string" SelectedOption="@selectedItem" SelectedOptionChanged="OnSelectedOptionChanged">
@foreach (var item in Items)
{
<div @key="item">
<MudRadio Option="@(item)" Color="Color.Primary">@item</MudRadio>
<MudButton OnClick="() => RemoveItem(item)" Variant="Variant.Filled">Remove</MudButton>
</div>
}
</MudRadioGroup>
Also your RemoveItem
method should also handle un-assigning the selectedItem
in the case when the selectedItem
is removed.
private void RemoveItem(string item)
{
if(selectedItem == item){
selectedItem = string.Empty;
}
Items.Remove(item);
}