I am authoring an Angular library. It contains a service, which runs initialization logic in the constructor that is required for the library to work properly. I have set up the library module with a static forRoot()
method like the following:
@NgModule({
imports: [CommonModule],
})
export class LibModule {
static forRoot(
config?: Partial<LibConfig>,
): ModuleWithProviders<LibModule> {
return {
ngModule: LibModule,
providers: [{ provide: MY_LIB_CONFIG, useValue: config }],
};
}
// This is necessary, so the service is constructed, even if the service is never injected
constructor(private myLibService: MyLibService) {}
}
Note the constructor where the lib service is injected. Without the constructor, the service initialization logic would only run if the library consumer injects the service, which is not what I want. The service should always be constructed. This works fine for me.
Now I want to offer a more standalone friendly provideMyLib()
function. Here is what I implemented so far:
export function provideMyLib(config?: Partial<LibConfig>): EnvironmentProviders {
return makeEnvironmentProviders([
{ provide: MY_LIB_CONFIG, useValue: config },
]);
}
It works fine in general, but the same problem here, the service is only constructed when the consumer injects it. What I have tried to fix it:
inject()
function inside the provideMyLib()
function -> Error: inject
must be run in injection context{ provide: MyLibService, ... }
-> service is not constructedI have also researched implementations of various provide*
functions in the Angular repository, didn't find anything. How can I implement my provide function?
If you're looking to init something, you need to hook it up to the ENVIRONMENT_INITIALIZER
:
export function provideMyLib(config?: Partial<LibConfig>): EnvironmentProviders {
return makeEnvironmentProviders([
{ provide: MY_LIB_CONFIG, useValue: config }
{
provide: ENVIRONMENT_INITIALIZER,
useValue: () => {
inject(MyLibService)
// do whatever you want here
},
}
}
}