Open Closed

After upgrading to Abp 9 our sidebar is missing #10016


User avatar
0
JanneHarju created
  • Exception message and full stack trace: -
  • Steps to reproduce the issue:

We are using lepton theme with angular. Angular is updated to 20 when Abp was updated to 9.3.4. Now after updates I managed to get UI open there is no side bar at left. I noticed in browser that there is empty layout inside dynamic layout instead of application layout which contains all necessary things. Do you have experience with Abp 9 with lepton theme?


9 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • With ABP 9.x and Angular 20, the LeptonX theme and its layout system have changed. In recent versions, the side menu and layout components were refactored, and some component names were updated. If your sidebar is missing, it is likely due to outdated imports or configuration.

    Steps to resolve:

    1. Update LeptonX Theme Packages

      • Ensure you are using the latest compatible version of @abp/ng.theme.lepton-x (for open-source) or @volosoft/abp.ng.theme.lepton-x (for commercial) that matches your ABP version.
    2. Update Angular Module Imports

      • In your app.module.ts, remove any old Lepton/LeptonX theme modules and import the new ones:
    import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x';
         import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts';
    
         @NgModule({
           imports: [
             // ...
             ThemeLeptonXModule.forRoot(),
             SideMenuLayoutModule.forRoot(),
           ],
           // ...
         })
         export class AppModule {}
    
    • For commercial: use @volosoft/abp.ng.theme.lepton-x and AbpSideMenuLayoutModule.
    1. Check angular.json Styles
      • Remove any direct Bootstrap CSS import. Add the LeptonX CSS and Bootstrap Icons:
    "styles": [
           "node_modules/@volo/ngx-lepton-x.lite/styles/sidemenu-layout.min.css",
           "node_modules/bootstrap-icons/font/bootstrap-icons.css"
         ]
    
    • For commercial, use the corresponding @volosoft/ngx-lepton-x paths.
    1. Migration Changes

      • In ABP 7.0+, the layout component names changed:
        • eThemeLeptonXComponents.NavbareThemeLeptonXComponents.Toolbar
        • eThemeLeptonXComponents.SidebareThemeLeptonXComponents.Navbar
      • If you use replaceable components, update their references as per the new naming.
    2. Clear Cache and Rebuild

      • Delete node_modules, run npm install or yarn, and rebuild your project.
    3. Verify Layout Usage

      • Ensure your main layout uses the correct dynamic layout selector for LeptonX. If you customized layouts, update them to use the new component structure.

    If you still see an empty layout:

    • Double-check that you are not mixing old and new LeptonX modules.
    • Compare your app.module.ts and angular.json with a fresh ABP 9.x Angular template using LeptonX.

    References:


    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
    JanneHarju created

    So we are not using LeptonX-theme. We have exported theme-lepton in our angular project and we have made some modifications. It was working in 8.3.4 version what we were using earlier.

  • User Avatar
    0
    JanneHarju created

    Here is our ThemeLeptonModule if problem is related to it:

    import { APP_INIT_ERROR_HANDLERS, CoreModule } from '@abp/ng.core';
    import { ThemeSharedModule } from '@abp/ng.theme.shared';
    import { ModuleWithProviders, NgModule } from '@angular/core';
    import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
    import {
      NgxValidateCoreModule,
      VALIDATION_ERROR_TEMPLATE,
      VALIDATION_INVALID_CLASSES,
      VALIDATION_TARGET_SELECTOR,
    } from '@ngx-validate/core';
    import { PROFILE_PICTURE_PROVIDERS } from '@volo/abp.commercial.ng.ui/config';
    import { AccountLayoutComponent } from './components/account-layout/account-layout.component';
    import { AccountLogoComponent } from './components/account-layout/account-logo/account-logo.component';
    import { AuthWrapperComponent } from './components/account-layout/auth-wrapper/auth-wrapper.component';
    import { TenantBoxComponent } from './components/account-layout/tenant-box/tenant-box.component';
    import { ApplicationLayoutComponent } from './components/application-layout/application-layout.component';
    import { CurrentUserImageComponent } from './components/current-user-image/current-user-image.component';
    import { EmptyLayoutComponent } from './components/empty-layout/empty-layout.component';
    import { FooterComponent } from './components/footer/footer.component';
    import { HeaderComponent } from './components/header/header.component';
    import { HttpErrorComponent } from './components/http-error/http-error.component';
    import { LogoComponent } from './components/logo/logo.component';
    import { CurrentUserComponent } from './components/nav-items/current-user.component';
    import { FullScreenComponent } from './components/nav-items/full-screen.component';
    import { LanguagesComponent } from './components/nav-items/languages.component';
    import { NavItemsComponent } from './components/nav-items/nav-items.component';
    import { NavbarMobileComponent } from './components/navbar-mobile/navbar-mobile.component';
    import { NavbarComponent } from './components/navbar/navbar.component';
    import { PageAlertContainerComponent } from './components/page-alert-container/page-alert-container.component';
    import { RoutesComponent } from './components/routes/routes.component';
    import { SettingsComponent } from './components/settings/settings.component';
    import { SidebarComponent } from './components/sidebar/sidebar.component';
    import { ValidationErrorComponent } from './components/validation-error/validation-error.component';
    import { LEPTON_THEME_NAV_ITEM_PROVIDERS } from './providers/nav-item.provider';
    import { LEPTON_THEME_SETTING_TAB_PROVIDERS } from './providers/setting-tab.provider';
    import { LEPTON_THEME_STYLES_PROVIDERS, removeLeptonLoader } from './providers/styles.provider';
    import { LEPTON_THEME_USER_MENU_PROVIDERS } from './providers/user-menu.provider';
    import { CUSTOM_STYLE } from './tokens/custom-style.token';
    import { LEPTON_THEME_FEATURES_PROVIDERS } from './tokens/features.token';
    import { CONTENT_AFTER_ROUTES, CONTENT_BEFORE_ROUTES } from './tokens/routes-content.token';
    import { AngularSvgIconModule } from 'angular-svg-icon';
    import { FeatureBadgeModule } from '@SCM/common/base-forms/components/feature-badge/feature-badge.module';
    import { Options } from './models/theme-lepton';
    
    export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, EmptyLayoutComponent];
    
    const COMPONENTS = [
      SettingsComponent,
      ValidationErrorComponent,
      HttpErrorComponent,
      LogoComponent,
      RoutesComponent,
      NavItemsComponent,
      CurrentUserImageComponent,
      LanguagesComponent,
      CurrentUserComponent,
      FullScreenComponent,
      NavbarComponent,
      NavbarMobileComponent,
      HeaderComponent,
      FooterComponent,
      SidebarComponent,
      PageAlertContainerComponent,
      AuthWrapperComponent,
      TenantBoxComponent,
      AccountLogoComponent,
    ];
    
    @NgModule({
      declarations: [...LAYOUTS, ...COMPONENTS],
      exports: [...LAYOUTS, ...COMPONENTS],
      imports: [
        CoreModule,
        ThemeSharedModule,
        NgbDropdownModule,
        NgxValidateCoreModule,
        AngularSvgIconModule,
        FeatureBadgeModule
      ],
    })
    export class BaseThemeLeptonModule { }
    
    @NgModule({
      exports: [BaseThemeLeptonModule],
      imports: [BaseThemeLeptonModule],
    })
    export class ThemeLeptonModule {
      static forRoot(options = {} as Options): ModuleWithProviders<ThemeLeptonModule> {
        return {
          ngModule: ThemeLeptonModule,
          providers: [
            LEPTON_THEME_NAV_ITEM_PROVIDERS,
            LEPTON_THEME_USER_MENU_PROVIDERS,
            LEPTON_THEME_STYLES_PROVIDERS,
            LEPTON_THEME_SETTING_TAB_PROVIDERS,
            PROFILE_PICTURE_PROVIDERS,
            LEPTON_THEME_FEATURES_PROVIDERS,
            {
              provide: VALIDATION_ERROR_TEMPLATE,
              useValue: ValidationErrorComponent,
            },
            {
              provide: VALIDATION_INVALID_CLASSES,
              useValue: 'input-validation-error',
            },
            {
              provide: VALIDATION_TARGET_SELECTOR,
              useValue: '.form-control',
            },
            {
              provide: CONTENT_AFTER_ROUTES,
              useValue: options.contentAfterRoutes || [],
            },
            {
              provide: CONTENT_BEFORE_ROUTES,
              useValue: options.contentBeforeRoutes || [],
            },
            {
              provide: CUSTOM_STYLE,
              useValue: options.customStyle || false,
            },
            {
              provide: APP_INIT_ERROR_HANDLERS,
              useValue: removeLeptonLoader,
              multi: true,
            },
          ],
        };
      }
    }
    
  • User Avatar
    0
    JanneHarju created

    And features.token.ts looks like this

    import { ConfigStateService, featuresFactory } from '@abp/ng.core';
    import { inject, InjectionToken, provideAppInitializer } from '@angular/core';
    import { ModuleVisibility, setModuleVisibilityFactory } from '@volo/abp.commercial.ng.ui/config';
    import { SettingTabsService } from '@abp/ng.setting-management/config';
    import { Observable } from 'rxjs';
    import { eLeptonThemeSettingTabNames } from '../enums/setting-tab-names';
    
    export const LEPTON_THEME_FEATURES = new InjectionToken<Observable<ModuleVisibility>>(
      'LEPTON_THEME_FEATURES',
      {
        providedIn: 'root',
        factory: () => {
          const configState = inject(ConfigStateService);
          const featureKey = 'LeptonManagement.Enable';
          const mapFn = features => ({
            enable: features[featureKey].toLowerCase() !== 'false',
          });
    
          return featuresFactory(configState, [featureKey], mapFn);
        },
      },
    );
    
    export const SET_LEPTON_THEME_SETTING_TAB_VISIBILITY = new InjectionToken(
      'SET_LEPTON_THEME_SETTING_TAB_VISIBILITY',
      {
        providedIn: 'root',
        factory: () => {
          const settingTabs = inject(SettingTabsService);
          const stream = inject(LEPTON_THEME_FEATURES);
    
          setModuleVisibilityFactory(
            stream,
            settingTabs,
            eLeptonThemeSettingTabNames.LeptonThemeManagement,
          ).subscribe();
        },
      },
    );
    
    export const LEPTON_THEME_FEATURES_PROVIDERS = [
      provideAppInitializer(() => {
        inject(SET_LEPTON_THEME_SETTING_TAB_VISIBILITY);
        return;
      }),
    ];
    
  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello,

    Thank you for explaining your problem by giving details. Since you have migrated from 8.3.4 to 9.3.4 , I need to remind you that we have made some set of adjustments on our side. The most important one is the standalone migration.

    You can check details from here

    1. 🔗 Migration guides
    2. 🔗 9.3 Migration
    3. 🔗 Standalone support

    If you have also migrated your application to the new builder system, this could make a difference.

    Thant is to say, the module and the token you have shared seem functional and not problematic. However, that would be the best if you could share

    • how you have provided them
    • the customizations you have done that could affect here

    If you prefer, you could also share a minimal reproducible example via e-mail. Here is my address: sumeyye.kurtulus@volosoft.com

    Thank you for your cooperation.

  • User Avatar
    0
    JanneHarju created

    Do you mean that how I provide LEPTON_THEME_FEATURES_PROVIDERS? Because SET_LEPTON_THEME_SETTING_TAB_VISIBILITY and LEPTON_THEME_FEATURES are only used in this features.token.ts file. ThemeLeptonModule is only one where LEPTON_THEME_FEATURES_PROVIDERS is in provided list.

    Do you believe that problem might be related to those injection tokens what I provided earlier? This was how they were earlier before I removed APP_INITIALIZER usage.

    export const LEPTON_THEME_FEATURES_PROVIDERS = [
      {
        provide: APP_INITIALIZER,
        useFactory: noop,
        deps: [SET_LEPTON_THEME_SETTING_TAB_VISIBILITY],
        multi: true,
      },
    ];
    

    I have used that new angular build system already in 8.3.4 version. I have read all those related migration guides. Our project is so big so for now we are staying with module style and not going to switch to standalone components. I have tried that angular standalone migration tool but it didn't made good work so it would be huge work to migrate rest by hand and figure out what modules/components need to be imported into each component. We have over 320 components and over 184 modules. It would be quite hard to provide any minimal reproducible example because we are no going to share all of our code and I have no idea what parts are related. Maybe theme-lepton module? I do not have list about what customizations we have done to lepton-theme.

    Problem might be related to how layout is selected. Now there is empty layout in use. Are these keys changed at your side?

  • User Avatar
    0
    JanneHarju created

    Here is what I get from application-configuration related to lepton theme So I didn't figure out yet how layout is selected (empty, application, account)

  • User Avatar
    0
    JanneHarju created

    I just tried how this would work and it seems that it fixed issue but I don't think this is correct solution. So I replaced empty layout component with application lyout component.

    export function initLayouts(injector: Injector) {
      const replaceableComponents = injector.get(ReplaceableComponentsService);
      replaceableComponents.add({
        key: eThemeLeptonComponents.ApplicationLayout,
        component: ApplicationLayoutComponent,
      });
      replaceableComponents.add({
        key: eThemeLeptonComponents.AccountLayout,
        component: AccountLayoutComponent,
      });
      replaceableComponents.add({
        key: eThemeLeptonComponents.EmptyLayout,
        component: ApplicationLayoutComponent,
      });
    }
    
  • User Avatar
    0
    sumeyye.kurtulus created
    Support Team Angular Expert

    Hello again,

    Thank you for providing extra details. I am suspecting that the abp-application-layout is not initialized correctly. Do you see any error thrown somewhere like this

    export function injectStyle(injector: Injector) {
      const rendererFactory = injector.get(RendererFactory2);
      const domInsertion = injector.get(DomInsertionService);
      const _document = injector.get(DOCUMENT);
    
      rendererFactory
        .createRenderer(_document.body, null)
        .addClass(_document.body, 'abp-application-layout');
    
      const appStyles: HTMLElement = _document.querySelector('link[rel="stylesheet"][href*="styles"]');
      let content: StyleContentStrategy;
      if (appStyles) {
        const domStrategy = DOM_STRATEGY.BeforeElement(appStyles);
        content = new StyleContentStrategy(styles, domStrategy, undefined, {
          id: LEPTON_STYLE_ELEMENT_ID,
        });
      } else {
        content = CONTENT_STRATEGY.AppendStyleToHead(styles, { id: LEPTON_STYLE_ELEMENT_ID });
      }
    
      domInsertion.insertContent(content);
    }
    
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on October 20, 2025, 13:25