I created a core library for my project containing some components and services. I built the library with ng-packagr. In the consuming project which references the library I built my webapp containing components provided by the library. Nothing special so far. But sometimes I want a component (coming from my lib) calling a method from a Service outside of the lib. Is this possible? Can I somehow inject a service to a component which is defined inside a library?
Cheers
I've achieved this before with something like this:
Your library's service(s) should be defined as an interface rather than as a concrete implementation (as is done in OO languages quite often). If your implementing application will only sometimes want to pass in its own version of the service then you should create a Default service in your library, and use it as so:
import { Component, NgModule, ModuleWithProviders, Type, InjectionToken, Inject, Injectable } from '@angular/core';
export interface ILibService {
aFunction(): string;
}
export const LIB_SERVICE = new InjectionToken<ILibService>('LIB_SERVICE');
export interface MyLibConfig {
myService: Type<ILibService>;
}
@Injectable()
export class DefaultLibService implements ILibService {
aFunction() {
return 'default';
}
}
@Component({
// whatever
})
export class MyLibComponent {
constructor(@Inject(LIB_SERVICE) libService: ILibService) {
console.log(libService.aFunction());
}
}
@NgModule({
declarations: [MyLibComponent],
exports: [MyLibComponent]
})
export class LibModule {
static forRoot(config?: MyLibConfig): ModuleWithProviders {
return {
ngModule: LibModule,
providers: [
{ provide: LIB_SERVICE, useClass: config && config.myService || DefaultLibService }
]
};
}
}
Then in your implementing application you have the ability to pass in the optional config via your library's forRoot
method (note that forRoot
should only be called once per application and at the highest level possible). Note that I've marked the config
parameter as optional, so you should call forRoot
even if you have no config to pass.
import { NgModule, Injectable } from '@angular/core';
import { LibModule, ILibService } from 'my-lib';
@Injectable()
export class OverridingService implements ILibService {
aFunction() {
return 'overridden!';
}
}
@NgModule({
imports: [LibModule.forRoot({ myService: OverridingService })]
})
export class ImplementingModule {
}
This was from memory as I don't have the code to hand at the moment so if it doesn't work for any reason let me know.