diff --git a/Radzen.Blazor.Tests/TabsTests.cs b/Radzen.Blazor.Tests/TabsTests.cs index def53ebaa..b6c40d72b 100644 --- a/Radzen.Blazor.Tests/TabsTests.cs +++ b/Radzen.Blazor.Tests/TabsTests.cs @@ -230,6 +230,27 @@ namespace Radzen.Blazor.Tests Assert.True(component.RenderCount > renderCountBefore); } + [Fact] + public void Tabs_ChangeHandlerThrows_StillRendersSelectedTab() + { + using var ctx = new TestContext(); + + var component = ctx.RenderComponent(parameters => parameters + .Add(p => p.SelectedIndex, 0) + .Add(p => p.Change, (int _) => throw new System.InvalidOperationException("boom")) + .Add(p => p.Tabs, TabsFragmentWithContent(("First", "First-Content"), ("Second", "Second-Content"))) + ); + + Assert.Contains("First-Content", component.Markup); + + var secondTab = component.FindAll("button[role='tab']")[1]; + var ex = Record.Exception(() => secondTab.Click()); + + Assert.NotNull(ex); + Assert.Contains("Second-Content", component.Markup); + Assert.DoesNotContain("First-Content", component.Markup); + } + [Fact] public void Tabs_NonNavigationKeyDown_DoesNotBlockSubsequentRenders() { diff --git a/Radzen.Blazor/RadzenTabs.razor.cs b/Radzen.Blazor/RadzenTabs.razor.cs index cf6e19c9c..c75859594 100644 --- a/Radzen.Blazor/RadzenTabs.razor.cs +++ b/Radzen.Blazor/RadzenTabs.razor.cs @@ -210,22 +210,27 @@ namespace Radzen.Blazor SetFocusedIndex(); - if (raiseChange) + try { - await Change.InvokeAsync(selectedIndex); - - await SelectedIndexChanged.InvokeAsync(selectedIndex); - - try - { - await Element.FocusAsync(preventScroll: true); - } - catch (JSDisconnectedException) + if (raiseChange) { + await Change.InvokeAsync(selectedIndex); + + await SelectedIndexChanged.InvokeAsync(selectedIndex); + + try + { + await Element.FocusAsync(preventScroll: true); + } + catch (JSDisconnectedException) + { + } } } - - StateHasChanged(); + finally + { + StateHasChanged(); + } } /// @@ -342,9 +347,15 @@ namespace Radzen.Blazor } shouldRender = false; - await Change.InvokeAsync(selectedIndex); - await SelectedIndexChanged.InvokeAsync(selectedIndex); - shouldRender = true; + try + { + await Change.InvokeAsync(selectedIndex); + await SelectedIndexChanged.InvokeAsync(selectedIndex); + } + finally + { + shouldRender = true; + } try {