Hello
Following the examples from IdentityConfig I have created 2 modules: StockTypesConfig: contains the service that will add a new menu item and a new child to that menu item StockTypes: has the components and routes
StockTypesConfigModule is loaded on app.module with the other ConfigModules, it is virtually identical to IdentityConfigModule:
StockTypesConfigModule:
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { noop } from '@abp/ng.core';
import { StockTypesConfigService } from './stock-types-config.service';
@NgModule({
providers: [{provide: APP_INITIALIZER, deps:[StockTypesConfigService], useFactory: noop, multi: true}],
})
export class StockTypesConfigModule { }
StockTypesConfigService:
import { Injectable } from '@angular/core';
import { addAbpRoutes, eLayoutType } from '@abp/ng.core';
@Injectable({
providedIn: 'root'
})
export class StockTypesConfigService {
constructor() {
addAbpRoutes([
{
name: 'Inventory',
path: '',
order: 1,
wrapper: true
},
{
name: 'Stock Types',
path: 'inventory/stock-types',
order: 2,
parentName: 'Inventory',
layout: eLayoutType.application
},
])
}
}
this method does seem to create the children the same way the administration menu seems to handle it in identity-config.service.ts also the url seems to be incorrect: http://localhost:4200/inventory/stock-types/undefined
Any ideas what else I could be missing to achieve the parent/child menu structure?
5 Answer(s)
-
0
Hi @rbarbosa
Can you share your
app.routing.module.ts
content to us? -
0
import {ABP, AuthGuard, PermissionGuard} from '@abp/ng.core'; import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; import {ApplicationLayoutComponent} from "@volo/abp.ng.theme.lepton"; const routes: Routes = [ { path: '', loadChildren: () => import('./home/home.module').then(m => m.HomeModule), data: { routes: { name: '::Menu:Home', iconClass: 'fa fa-home' } as ABP.Route } }, { path: 'inventory', loadChildren: () => import('./inventory/inventory.module').then(m => m.InventoryModule) }, { path: 'identity', loadChildren: () => import('@volo/abp.ng.identity').then(m => m.IdentityModule) }, { path: 'account', loadChildren: () => import('@volo/abp.ng.account').then(m => m.AccountModule) }, // the rest of @volo modules: @volo/abp.ng.language-management @volo/abp.ng.saas // @volo/abp.ng.audit-logging @volo/abp.ng.identity-server { path: 'setting-management', loadChildren: () => import('@abp/ng.setting-management').then(m => m.SettingManagementModule) }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
and Inventory Loads Stock Types:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: '', redirectTo: 'stock-types' }, { path: 'stock-types', loadChildren: () => import('./stock-types/stock-types.module').then(m => m.StockTypesModule) }]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class InventoryRoutingModule { }
I started playing around and found that there is a ConfigStateService.dispatchAddRoute Method so i changed my StockTypeModuleConfigModule to do this instead:
import { Injectable } from '@angular/core'; import { addAbpRoutes, eLayoutType, AddRoute } from '@abp/ng.core'; import { ConfigStateService } from '@abp/ng.core'; @Injectable({ providedIn: 'root' }) export class StockTypesConfigService { constructor(private config: ConfigStateService) { this.config.dispatchAddRoute( { name: 'Inventory', path: '', order: 1 } ) this.config.dispatchAddRoute( { name: 'Stock Types', path: 'inventory/stock-types', order: 2, parentName: 'Inventory', layout: eLayoutType.application } ) } }
which leads to the route being added before init
so I changed the menu to be patched after the first tick: stock-types-config.service.ts
import { Injectable } from '@angular/core'; import { addAbpRoutes, eLayoutType, AddRoute } from '@abp/ng.core'; import { ConfigStateService } from '@abp/ng.core'; @Injectable({ providedIn: 'root' }) export class StockTypesConfigService { constructor(private config: ConfigStateService) { setTimeout(() => this.addRoutes()); } addRoutes():void{ this.config.dispatchAddRoute( { name: 'Inventory', path: '', order: 1 } ) this.config.dispatchAddRoute( { name: 'Stock Types', path: 'inventory/stock-types', order: 2, parentName: 'Inventory', layout: eLayoutType.application } ) } }
but i would love to know the 'proper' way to define routes from sub-modules
-
0
The
path
property accepts one level route like below:addAbpRoutes([ { name: 'Inventory', path: '', order: 1, wrapper: true, }, { name: 'Stock Types', path: 'inventory', order: 2, parentName: 'Inventory', layout: eLayoutType.application, children: [{ name: 'Stock Types', path: 'stock-types' }], }, ]);
But it seems a bug. We will be fixed.
The proper way is to add routes by using the
addAbpRoutes
function. You use theaddAbpRoutes
function after the bug is resolved.By the way, adding routes by using the
dispatchAddRoute
method, not a bad solution.Thanks for reporting.
-
0
Thank you, will update my sources when the packages receive the bugfix.
On the same vein, if I have this scenario:
Main application Module
- SubModuleA (SubModuleAConfigService)
- SubModuleB (SubModuleBConfigService)
and the menu structure is somewhat like this: Main menu -CategoryA --SubModuleA --SubModuleB
From a submodule perspective I should be defining the 'CategoryA' menu in all modules as they do not depend on each other, but sadly this creates duplicate CategoryA menu listings, would it be possible to 'patch' the menu structure rather than adding a clone? Taken from identity-config.service.ts if I remove this module, all other modules depending on the administration menu structure will fail, as they are not defining it.
-
0
For now, wrappers should be defined by just one module. We'll change the wrapper structure. Each module will be defined own wrapper category without duplication.