Using forRoot to pass configuration options into a library is a well used pattern in Angular.
TestLibModule.forRoot({
message: environment.message
})
If the library is lazy loaded though there is no opportunity to do this as the library will now be dynamically imported by the router.
const routes: Routes = [
{
path: 'test',
loadChildren: () => import('./test/test.module').then(m => m.TestModule)
}
];
There is a way (hack?) round this which I'll show below. If you want to skip to the code then it's here.
To get started create a project, an app (web-app) and the lazy loaded feature library (test-lib).
ng n ng-configurable-lazy-lib-sample --interactive=false --createApplication=false --routing=true
cd ng-configurable-lazy-lib-sample
ng g application web-app --routing=true --style=scss
ng g library test-lib
For this sample we want test-lib to have a setting, which will allow the message displayed by the test component to be set by the consuming application.
Add the following files under the test-lib/lib folder.
test-lib.config.ts
export interface TestlLibConfig {
message: string;
}
import { InjectionToken } from '@angular/core';
import { TestLibConfig } from './test-lib-config';
export const TEST_LIB_CONFIG = new InjectionToken(
'TEST_LIB_CONFIG'
);
This is the new part. Instead of using forRoot add a static settings property to the module along with a factory to provide the TEST_LIB_CONFIG, returning the settings.
export function SettingFactory() {
return TestLibModule.settings;
}
// @dynamic
@NgModule({
declarations: [TestComponent],
imports: [CommonModule, TestLibRoutingModule],
providers: [
{
provide: TEST_LIB_CONFIG,
useFactory: SettingFactory
}
]
})
export class TestLibModule {
static settings: TestLibConfig;
constructor() {}
}
Import the config into TestLibComponent and display the message property.
@Component({
selector: 'lib-test-lib',
template: `
<h2>Configurable message: {{ message }}</h2>
`,
styles: []
})
export class TestLibComponent implements OnInit {
message: string;
constructor(@Inject(TEST_LIB_CONFIG) private testLibConfig: TestLibConfig) {}
ngOnInit() {
this.message = this.testLibConfig.message;
}
}
Add a file test-lib-routing.module.ts under the lib folder as below.
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TestLibComponent } from './test-lib.component';
const routes: Routes = [
{ path: 'test', component: TestLibComponent },
{
path: '**',
redirectTo: 'test'
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class TestLibRoutingModule {}
Export all the new files by adding them to public-api.ts.
export * from './lib/test-lib-config';
export * from './lib/test-lib-config.token';
export * from './lib/test-lib-routing.module';
export * from './lib/test-lib.component';
export * from './lib/test-lib.module';
export * from './lib/test-lib.service';
Set up the route to the test-lib in app-routing.module.ts and set the library settings property.
const routes: Routes = [
{
path: 'test-lib',
loadChildren: () =>
import('test-lib').then(m => {
m.TestLibModule.settings = {
message: environment.message
};
return m.TestLibModule;
})
},
{
path: '**',
redirectTo: 'test-lib'
}
];
Replace the boilerplate app.component markup.
<h1>configurable lazy lib</h1>
<router-outlet></router-outlet>
Build the library and the app. The run the app
ng build test-lib
ng build web-app
ng s
Now run it and if everything has gone to plan you will see that that message value set in the app is displayed.