- 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)
-
0
- 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:
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.
- Ensure you are using the latest compatible version of
Update Angular Module Imports
- In your
app.module.ts
, remove any old Lepton/LeptonX theme modules and import the new ones:
- In your
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
andAbpSideMenuLayoutModule
.
- 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.
Migration Changes
- In ABP 7.0+, the layout component names changed:
eThemeLeptonXComponents.Navbar
→eThemeLeptonXComponents.Toolbar
eThemeLeptonXComponents.Sidebar
→eThemeLeptonXComponents.Navbar
- If you use replaceable components, update their references as per the new naming.
- In ABP 7.0+, the layout component names changed:
Clear Cache and Rebuild
- Delete
node_modules
, runnpm install
oryarn
, and rebuild your project.
- Delete
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
andangular.json
with a fresh ABP 9.x Angular template using LeptonX.
References:
- LeptonX Theme Angular Customization
- LeptonX Theme Integration Guide
- ABP 7.0 Migration Guide (Layout Changes)
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.
-
0
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.
-
0
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, }, ], }; } }
-
0
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; }), ];
-
0
Hello,
Thank you for explaining your problem by giving details. Since you have migrated from
8.3.4
to9.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
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.
-
0
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?
-
0
-
0
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, }); }
-
0
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 thisexport 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); }