RadzenTabs SelectedIndex renders different when using AuthorizeView

I have a question regarding tab selected index. I am using an AuthorizeView with policies for displaying RadzenTabsItem. I have one for HR to see everything, I have one for managers, and a tab for the employee themselves. The issue is when I use the code below, the third tab (Employee) is the one that loads as selected after rendering is complete and has an index of 0. When testing I see the index sequence for the tabs is 1,2,0. So setting selectedIndex = 0 does not help.

Depending on the type of person that is loading the page, they may see either 1, 2, or all 3 tabs. How can I ensure that the first tab as displayed on the page is the one that is always selected?

 <RadzenTabs @ref="tabs" @bind-SelectedIndex="selectedIndex">
     <Tabs>
         @* HR View *@
         <AuthorizeView Policy="@Policies.IsHrUser">
             <Authorized>
                 <RadzenTabsItem Text="All Employee Evaluations" >
                     <RadzenDataGrid 
			            ...                     
	                 </RadzenDataGrid>
                 </RadzenTabsItem>
             </Authorized>
         </AuthorizeView>
         @* Manager View *@
         <AuthorizeView Policy="@Policies.IsManager">
             <Authorized>
                 <RadzenTabsItem  Text="Employee Evaluations">
		             <RadzenDataGrid 
			             ...
                     </RadzenDataGrid>
                 </RadzenTabsItem>
             </Authorized>
         </AuthorizeView>
         @* Employee View *@
         <RadzenTabsItem Text="Your Evaluations">
             <RadzenDataGrid 
                ...
             </RadzenDataGrid>
         </RadzenTabsItem>
     </Tabs>
 </RadzenTabs>

The tab indices are assigned in the order the RadzenTabsItem components initialize, not the order they appear in markup. AuthorizeView renders its content asynchronously - on the initial render the policy checks are still pending, so only the tab that isn't wrapped in AuthorizeView exists and it gets index 0 and the default selection. The other tabs register later when authorization completes.

To avoid this, evaluate the policies in code and render the tabs only after the checks complete - this way all tabs initialize together, in markup order:

@if (loaded)
{
    <RadzenTabs @bind-SelectedIndex="selectedIndex">
        <Tabs>
            @if (isHrUser)
            {
                <RadzenTabsItem Text="All Employee Evaluations">
                    ...
                </RadzenTabsItem>
            }
            @if (isManager)
            {
                <RadzenTabsItem Text="Employee Evaluations">
                    ...
                </RadzenTabsItem>
            }
            <RadzenTabsItem Text="Your Evaluations">
                ...
            </RadzenTabsItem>
        </Tabs>
    </RadzenTabs>
}

@code {
    [Inject]
    IAuthorizationService AuthorizationService { get; set; }

    [CascadingParameter]
    Task<AuthenticationState> AuthenticationStateTask { get; set; }

    bool loaded;
    bool isHrUser;
    bool isManager;
    int selectedIndex;

    protected override async Task OnInitializedAsync()
    {
        var user = (await AuthenticationStateTask).User;

        isHrUser = (await AuthorizationService.AuthorizeAsync(user, Policies.IsHrUser)).Succeeded;
        isManager = (await AuthorizationService.AuthorizeAsync(user, Policies.IsManager)).Succeeded;

        loaded = true;
    }
}

Now the first tab on the page is always index 0 and is selected by default.

1 Like

That worked perfectly. Thank you very much.