当前位置: 动力学知识库 > 问答 > 编程问答 >

typescript - Angular2 DI: How to inject dependency under @NgModule?

问题描述:

TL;DR 25.10.16: update

I renamed the title to provide more clarification as i am still concerned about the right solution.

Given a module

@NgModule({

imports: [

ExternalModule.forRoot(config),

],

providers: [EXTERNAL_PROVIDERS(config)],

})

export class MyModule{}

So my questions are: is there any possibilty that i can inject a dependency with my passed config like this ?

  1. ExternalModule.forRoot(@Inject(MyConfig) config : MyConfig)
  2. providers: [EXTERNAL_PROVIDERS(@Inject(MyConfig) config)] (

I do not want to create {provide: xxx, deps :[xxx], useFactory : xxx} for each given external provider.

I tried to initialize a Application Wide Service Locator with access to the root injector as described here , but with Angular 2.1.0 ngDoBootstrap does not work as expected.

----------

Old Post:

I would like to know what the correct pattern is for configuring an external third party library provider in Angular2.

Let's take an example (code samples in Typescript):

There is a library that exposes its providers and offers some configuration options by config object literal:

export function THIRD_PARTY_PROVIDERS(config = {}): Provider[] {

return [

{

provide: ExtConfigurableService,

deps: [Http],

useFactory: (http: Http) => {

return new ExtConfigurableService(http, config);

}

},

ExtOtherService

];

}

Then on the client side, these providers can be included in an @NgModule:

@NgModule({

providers: [

THIRD_PARTY_PROVIDERS({foo : 'bar'})

],

})

export class ClientModule { }

But what if my configuration object itself has dependencies on an existent service like MyService?

I cannot inject a dependency in the providers array. The only way from my point of view is to use a FactoryProvider:

const myConfigProvider = {

provide: MyConfig,

deps: [MyService],

useFactory: (MyService) => {

return new MyConfig(MyService);

}

};

Given that, how can i inject MyConfig into THIRD_PARTY_PROVIDERS?


The only solutions which i came up with are not satisfactory:

  1. Use of an exported OpaqueToken from the third party provider side like here (Angular 2 Router)
  2. configure all providers manuallay from the client side

The first can only be done from the third party provider: export the token and require that token as own dependency in the factory provider.

The second is very ugly, because you have to know and configure the implementation details / services of the third party lib by yourself.

@NgModule({

providers: [

{provide: ExtConfigurableService, deps: [MyConfig], useFactory: ...},

ExtOtherService

],

})

export class ClientModule { }

What is the preferred pattern in angular 2 (client and third party provider side)?


Update 19.10.16

I implemented my first proposal for a solution and it works fine. But it requires that you have control over the external library / agree with the project owner on your changes or fork the repo.

third-party-lib.ts:

 export const JWT_CONFIGURATION = new OpaqueToken('THIRD_PARTY_PROVIDER_TOKEN');

...

@Injectable()

export class ExtConfigurableService {

constructor(@Inject(JWT_CONFIGURATION) config: any) {

// do someting with client provided config

}

my-module.ts

 @NgModule({

providers: [

{

provide: JWT_CONFIGURATION,

deps: [MyService],

useFactory: (mySvc: MyService) => {

return {foo : 'bar'};

}, THIRD_PARTY_PROVIDERS

]

})

export class MyModule { }

But if the external lib requires you to pass your config as an argument (like in the example at the top), i still don't know how to inject myconfig into it.

Has Angular 2 other ways to inject a dependency with @Inject() in addition to the constructor or the factory provider?

分享给朋友:
您可能感兴趣的文章:
随机阅读: