Open Closed

RouterTabs integration or alternative tabs solution in Blazor WebApp LeptonX #9679


User avatar
1
konstantinidis.f created

Context:
I am developing a Blazor Web App using the LeptonX theme with a side-menu layout. I have implemented a dynamic tab navigation system using Blazorise RouterTabs, by following the Blazorise documentation and customizing the layout as mentioned in the LeptonX documentation. My issue is similar to #9473

Problems:

  • Blazorise RouterTabs is inside the @Body of the layout and cannot render the other layout sections (e.g., LeptonX Breadcrumb, Toolbar, Footer) within each tab. As a result, routed components displayed in tabs lack the complete ABP layout structure, leading to inconsistent UI and missing theme elements.
  • When navigating to existing ABP pages (e.g., Tenant Management) within RouterTabs, the tab titles display raw route paths (e.g., Volo.Saas.Host.Blazor.Pages.Saas.Host.TenantManagement) instead of the localized page names defined in ABP resource file.

Request:
I am seeking a recommended approach or solution to implement a dynamic tab navigation system in a Blazor Web App that:

  • Fully integrates with the LeptonX theme, ensuring each tab renders the complete ABP layout (header, footer, etc.).
  • Displays localized tab titles for ABP pages, leveraging the existing ABP localization resources.

7 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent

    To implement a dynamic tab navigation system in a Blazor Web App using the LeptonX theme, while ensuring full theme integration and localized tab titles, follow these recommendations:

    1. Integrate Tabs at the Layout Level

      • Place your tab navigation (e.g., Blazorise RouterTabs) in the main layout (such as SideMenuLayout.razor), not inside the @Body.
      • This ensures that each tab renders within the complete ABP/LeptonX layout, including header, footer, breadcrumbs, and toolbars.

      Example (simplified):

    @inherits SideMenuLayout
    
       <TelerikRootComponent>
           <div id="lpx-wrapper">
               <MainHeader />
               <div class="lpx-content-container">
                   <div class="lpx-topbar-container">
                       <div class="lpx-topbar">
                           <Breadcrumbs />
                       </div>
                   </div>
                   <div class="lpx-content-wrapper">
                       <div class="lpx-content">
                           <RouterTabs>
                               <!-- Tab content will be rendered here -->
                           </RouterTabs>
                           <ContentToolbar />
                           <PageAlert />
                           <LayoutHook Name="@LayoutHooks.Body.First" Layout="@StandardLayouts.Application" />
                           @Body
                           <LayoutHook Name="@LayoutHooks.Body.Last" Layout="@StandardLayouts.Application" />
                           <DynamicLayoutComponent />
                           <UiMessageAlert />
                           <UiNotificationAlert />
                           <UiPageProgress />
                       </div>
                   </div>
                   <footer>
                       <Footer />
                   </footer>
               </div>
               <MobileNavbar />
               <div class="lpx-toolbar-container">
                   <MainHeaderToolbar />
               </div>
           </div>
       </TelerikRootComponent>
    
    • Adjust the placement of RouterTabs so it wraps or coordinates with the @Body and other layout elements.
    1. Ensure Routed Components Use the Layout

      • All routed pages/components should inherit from the same layout (e.g., SideMenuLayout).
      • This guarantees that when a page is rendered in a tab, it includes all theme elements.
    2. Localize Tab Titles

      • Instead of using the raw route or component name, fetch the localized display name for each tab.
      • Use ABP’s localization system to retrieve the display name for each page. For example:
    @inject IStringLocalizer<YourResource> L
    
         <RouterTabs>
             @foreach (var tab in Tabs)
             {
                 <Tab Title="@L[tab.LocalizationKey]">
                     <!-- Tab content -->
                 </Tab>
             }
         </RouterTabs>
    
    • For ABP built-in pages, use their resource keys (e.g., "Menu:TenantManagement").
    1. Dynamic Tab Management

      • Maintain a list of open tabs in a service or state container.
      • When navigating, add a new tab with the correct localized title and route.
    2. Alternative: Custom Tab System

      • If Blazorise RouterTabs cannot fully integrate with the ABP layout, consider building a custom tab system:
        • Use a shared service to track open tabs/routes.
        • Render each tab’s content using <RouteView> or <DynamicComponent>, ensuring each uses the correct layout.
        • Use ABP’s localization for tab titles.
    3. Reference Implementation

    By following this approach, you ensure that each tab renders with the full LeptonX/ABP layout and displays localized titles, providing a consistent and integrated user experience.

    Sources:


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    konstantinidis.f created

    I'm not sure the AI answer makes sense.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi

    Override the layout file is the right way. You can ignore the AI’s answer.

    Thanks.

  • User Avatar
    1
    konstantinidis.f created

    I have already overriden the layout file and replaced the @Body with the <Div Class="layout"><RouterTabs /></div> as described in the Blazorise documentation. The RouterTabs component captures the navigation of the pages and renders the page components into tabs. The problem is that the Toolbar is not part of the Body of each page, and thus it is not rendered inside the tab. Also, RouterTabs get the type of each page and place its name in the tab name.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Toolbar is not part of the Body of each page, and thus it is not rendered inside the tab.

    You can move the Toolbar component inside <Div Class="layout"><RouterTabs /></div>

    You can also rewrite all components by downloading the LeptonX theme source code.

    Thanks.

  • User Avatar
    1
    konstantinidis.f created

    The <div/> does not have any significance. The body of any page is rendered inside the <RouterTabs/> component. Unfortunately, <RouterTabs/> does not support layout sections inside it. It just renders the page's body.

    Rewriting the LeptonX source code or providing a custom layout would not help as the ABP pages expect any layout used to contain a Toolbar section. I could rewrite all the ABP pages to place their toolbar inside their body, but I would like to avoid that.

    Besides that, the RouterTabs component expects an attribute in each page to provide the name of the page. The ABP pages do not have this attribute and thus the RouterTabs component uses their type name as the name.

    Do you have an alternate suggestion to RouterTabs or a workaround to the above problems?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I don't have many suggestions. You can rewrite and replace all components and layout pages, and it should not prevent you from implementing it.

    Thanks.

Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 10, 2025, 06:30