Ok, it took me a while to figure this out.
TLDR: the forRoot
method must dead simple, otherwise the AOT compiler complains.
To make it simple, I had to:
Remove branching logic and function calls from the forRoot
method.
Implement the logic to map the items to routes into a factory provider, rather than inlining it inside the forRoot
method.
Use Router.resetConfig
to add the routes dynamically within the factory impelmentation.
Add an ANALYZE_FOR_ENTRY_COMPONENTS provider so that any components passed in would be added to entryComponents
automatically as part of the module.
Import RouterModule.forChild([])
into FeatureModule
because I use the components from @angular/router
.
Import RouterModule.forRoot([])
into AppModule
because it provides the application-wide Router
service.
Final Solution
export const Items = new InjectionToken<any[]>('items');
export function InitMyService(router:Router, items:any[]) {
var routes:Routes = items.map(t=> { return { path: t.name, component: t.component, outlet: 'modal' }});
var r = router.config.concat(routes);
router.resetConfig(r);
return new MyService(router);
}
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([])
],
declarations: [
MyComponent
],
exports: [
MyComponent
],
providers: [
]
})
export class FeatureModule {
static forRoot(items:any[]): ModuleWithProviders {
return {
ngModule: FeatureModule,
providers: [
{ provide: Items, useValue: items},
{ provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: items},
{ provide: MyService, useFactory: InitMyService, deps:[Router, Items] }
]
}
}
}
app.module.ts
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot([]),
FeatureModule.forRoot([{name: 'test', component: TestComponent}])
],
declarations: [ AppComponent, TestComponent ],
bootstrap: [ AppComponent ],
providers: [
],
exports: [AppComponent]
})
export class AppModule {
}
The key to solving this was the realization that RouterModule.forChild()
does not register any router services. This is intentional so that any module can import the RouterModule and take advantage of its components, without actually registering any services. At the AppModule level, I still needed to register the Router
service as a singleton by importing RouterModule.forRoot()
into AppModule.
Improved decorator error messages
. Maybe try to upgrade to the latest version and see if you can find a way to solve this. Sorry for not being to help more. blog.angular.io/angular-5-1-more-now-available-27d372f5eb4e – Peepulvar routes - data
and useproviders: [provideRoutes(data)]
? – ExpedientFeature
module you wroteimports: [ RouterModule.forRoot() ],
shouldn't it beforRoot([])
? Can you setup reproduction? – Expedientnpm install && ng build --prod
and everything works fine. stackblitz.com/edit/angular-k4deww – Phaih