Brandon Brandon - 1 month ago 14
AngularJS Question

Angular 2 cannot find declarations in higher-level modules

I have a nested module structure, organized by feature:

/app
/lib (not a module)
/pipes
capitalize.pipe.ts
/portal
/dashboard
/public


Each module has its own lazy loaded routes. Here's my app, portal and dashboard routes, with imports omitted for brevity:

**app.routing.ts**
export const appRouting: ModuleWithProviders = RouterModule.forRoot([
{
path: 'portal',
loadChildren: () => require('es6-promise!./portal/portal.module')('PortalModule')
},
{
path: '',
loadChildren: () => require('es6-promise!./public/public.module')('PublicModule')
}
])

**portal.routing.ts**
export const portalRouting: ModuleWithProviders = RouterModule.forChild([
{
path: 'portal',
component: PortalComponent,
children: [
{
path: 'dashboard',
loadChildren: () => require('es6-promise!./dashboard/dashboard.module')('DashboardModule')
},
],
canActivate: [AuthenticationRequired]
}
]);

**dashboard.routing.ts**
export const dashboardRouting: ModuleWithProviders = RouterModule.forChild([
{
path: '',
component: DashboardComponent
}
]);


The problem I'm seeing is that if I add a declaration to my app.module.ts, like
CapitalizePipe
, it is not available in a lazy loaded module. It will only work at the app component level.

I receive:

Template Error: The pipe 'capitalize' could not be found


if I try to implement the pipe in dashboard.component.html for example.

It was my expectation that if I add an "app level" declaration, that it would be available to any module below that.

What am I doing wrong?

Answer

The problem I'm seeing is that if I add a declaration to my app.module.ts, like CapitalizePipe, it is not available in a lazy loaded module

This is true for modules whether the modules are lazy-loaded or not. @NgModule.declaratations (i.e. components, directives, and pipes) are scoped to the module that declares them (unless that module exports them, then they can be used in other modules that import this module).

If you you have declarations that should be shared, it's recommended to declare and export them in a shared module, and import that shared module into whatever module you want to use the items in.

@NgModule({
  declarations: [ CapitalizePipe, otherStuff ],
  exports: [ CapitalizePipe, otherStuff ]
})
class SharedModule {}

@NgModule({
  imports: [ SharedModule ]
  declarations: [ ComponentThatUsesCapitlizePipe ],
  exports: [ ComponentThatUsesCapitlizePipe  ]
})
class OtherModule {}