When moving a module into a library the using the Angular cli environment settings is no longer an option. This post shows another option for supporting configuration settings in the module. There is already a common pattern for configuring a module using forRoot. With a few changes this can be used to for a library as well.
There is a sample for the post available here. If you want to jump to the good bits just clone the repo and skip the rest of this section.
git clone https://github.com/JayChase/ng-configurable-libs-sample.git
npm i
To get started create a project, an app (web-app) and a library (normal-lib).
ng n ng-configurable-libs-sample --interactive=false --createApplication=false
cd ng-configurable-libs-sample
ng g application web-app --routing=true
ng g library normal-lib
For this sample we want normal-lib to have a setting which will allow the message displayed by the test component to be set by the consuming application. To do this follow the normal forRoot pattern.
Add the following files under the normal-lib/lib folder: normal-lib.config.ts
export interface NormalLibConfig {
message: string;
}
import { InjectionToken } from '@angular/core';
import { NormalLibConfig } from './normal-lib-config';
export const NORMAL_LIB_CONFIG = new InjectionToken(
'NORMAL_LIB_CONFIG'
);
export * from './lib/normal-lib-config';
export * from './lib/normal-lib.component';
export * from './lib/normal-lib.module';
export * from './lib/normal-lib.service';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { NormalLibConfig } from './normal-lib-config';
import { NORMAL_LIB_CONFIG } from './normal-lib-config.token';
import { NormalLibComponent } from './normal-lib.component';
@NgModule({
declarations: [NormalLibComponent],
imports: [
],
exports: [NormalLibComponent]
})
export class NormalLibModule {
static forRoot(normalLibConfig: NormalLibConfig): ModuleWithProviders {
return {
ngModule: NormalLibModule,
providers: [
{
provide: NORMAL_LIB_CONFIG,
useValue: normalLibConfig
}
]
};
}
}
In normal-lib.component.ts (the component created by default by ng g library) inject the config and use it.
import { Component, Inject } from '@angular/core';
import { NormalLibConfig } from './normal-lib-config';
import { NORMAL_LIB_CONFIG } from './normal-lib-config.token';
@Component({
selector: 'lib-normal-lib',
template: `
<h2>Configurable message: {{ message }}</h2>
`,
styles: []
})
export class NormalLibComponent {
message = this.normalLibConfig.message;
constructor(@Inject(NORMAL_LIB_CONFIG) private normalLibConfig: NormalLibConfig) { }
}
Finally build the library.
ng build normal-lib
In the web-app environments files add a message property.
export const environment = {
...
message: 'message'
};
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NormalLibModule } from 'normal-lib';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
NormalLibModule.forRoot({
message: environment.message
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Now the library module is imported and configured use the NormalLibComponent in the app to check everything is working. app.component.html
<div style="text-align:center">
<h1>
ng configurable libs sample
</h1>
</div>
<lib-normal-lib></lib-normal-lib>
<router-outlet></router-outlet>
Now if you run the app the message value from environment.ts will be displayed.
ng s
There is one common library type that this approach cannot be used for: lazy loaded feature modules. These require a different approach which will be covered in the next post.