2

I have a MetaManager class:

@Injectable()
export class MetaManager{

    constructor(private handlers:Handler[]){
        console.log(handlers);
    }
}

this class needs a Handler[] to register as handlers. Than, when I get some metadata, I loop in my handlers array to see which one can handler my meta entry.

Having said that, problem is that I can't provide an array of class as config in main.ts, here is what I have tried (and what did not work):

Using String entry (with a @Provide('HANDLERS') annotation in MetaManager:

`bootstrap(AppComponent, [MetaManager,provide('HANDLERS', {useValue: [DebugHandler]}) ]);`

Using an interface to provide handlers:

export const HANDLERS: HandlerConfig = {handlers: [<Handler>DebugHandler]};

bootstrap(AppComponent, [MetaManager, provide(HandlerConfig, {useValue: HANDLERS}) ]);

Using a Handler[] class provider:

bootstrap(AppComponent, [MetaManager, provide(Handler[], [DebugHandler])]);

I want to provide a class array because MetaManager will need to have more than one Handler in the future, notification, error, etc...

EDIT:

Using multi provider gives me a No provider for Array! (ApiService -> MetaManager -> Array) Error:

meta-manager.ts:

@Injectable()
export class MetaManager{

    constructor(private handlers:Handler[]){
        console.log(handlers);
    }
}

main.ts:

bootstrap(AppComponent,
    [   MetaManager,
        provide(Handler, {useClass: DebugHandler, multi: true}),
        provide(Handler, {useClass: NotificationHandler, multi: true})]);
Supamiu
  • 8,501
  • 7
  • 42
  • 76

1 Answers1

9

You could use the multi attribute when registering your providers for the Handler class:

bootstrap(AppComponent, [
  MetaManager,
  provide(Handler, { useClass: DebugHandler, multi: true }),
  provide(Handler, { useClass: OtherHandler, multi: true })
]);

This way, you will be able to inject this way:

@Injectable()
export class MetaManager{
  constructor(@Inject(Handler) private handlers:Handler[]){
    console.log(handlers);
  }
}

Here is the corresponding plunkr: https://plnkr.co/edit/UBIvWfOvAmo4XO2ohbID?p=preview. This article could interest you:

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • yes but what if I want to get every Handler registered? also, how to get every one of them? – Supamiu Mar 24 '16 at 17:03
  • The injected array contains all registered handlers. Perhaps I misunderstood your question. I updated my answer... – Thierry Templier Mar 24 '16 at 17:04
  • With the multi approach you need to register providers one by one. All the registered providers for this token will be provided as an array... – Thierry Templier Mar 24 '16 at 17:07
  • I just finished to try your example, I get a "no provider found for Array" error, seems like I don't get a Handler[] – Supamiu Mar 24 '16 at 17:13
  • Sorry for double comment, could not edit the last one. I edited my question to show you what I tried, and the exact error. – Supamiu Mar 24 '16 at 17:19
  • Yes, you're right I missed the `@Inject(Provider)` at the constructor level. It works with this. I updated my answer and added a plunkr... – Thierry Templier Mar 24 '16 at 17:20
  • Everything works fine, thank you :D Do I have a way to export a provider which provides this array? like a shorthand because I have to provide it in main.ts and in every spec.ts file using MetaManager – Supamiu Mar 24 '16 at 17:27
  • You could try useValue instead if useClass and return the array in it. The injection would demain the same... – Thierry Templier Mar 24 '16 at 17:32