1

I couldn't figure out the right way to do it, but here is what I want to achieve:

  • abstract class Engine

  • class TurboEngine extends Engine

  • class RocketEngine extends Engine

I have an angular application which is injecting 'Engine' in a lot of places and using it's methods to fulfill the business needs.

My only problem is that I have to inject TurboEngine and RocketEngine at the same time on every places and with a condition, decide which to call.

This is what I want to change. Since I have an abstract Engine, I'd like to inject it ONCE in my main component, and then having injected automatically by that way in my components.

So basically defining the provider for a service at runtime.

Here is what I've tried, but didn't work:

var injector = ReflectiveInjector.resolveAndCreate([
    provide(Engine, {useClass: TurboEngine})
]);

I did it in my main component where it worked, but all other places I've got the following error:

No provider for TurboEngine! (Engine -> TurboEngine)

Updated:

The way I want to use it:

  • I have component A which injects Engine (that's where I want to choose an implementation, so either TurboEngine or RocketEngine based on some conditions.

  • Then I have component B, which is inside component A's template. Here when I'm trying to inject Engine I would expect to have the same instantiated object as I manually created in component A

Iamisti
  • 1,680
  • 15
  • 30
  • What version are you using? – acdcjunior Aug 01 '16 at 15:05
  • "@angular/common": "2.0.0-rc.4", "@angular/compiler": "2.0.0-rc.4", "@angular/core": "2.0.0-rc.4", "@angular/forms": "0.2.0", "@angular/http": "2.0.0-rc.4", "@angular/platform-browser": "2.0.0-rc.4", "@angular/platform-browser-dynamic": "2.0.0-rc.4", "@angular/router": "3.0.0-beta.2", – Iamisti Aug 01 '16 at 15:07
  • and 'provide' is deprecated as well...so... – Iamisti Aug 01 '16 at 15:07

1 Answers1

0

ReflectiveInjector.resolveAndCreate([...]) creates a new and independent injector that only knows about Engine and is entirely unrelated to the injector used by your Angular application.

You need to provide Engine with bootstrap(...) or at the root component and inject Engine where you need it.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • thanks, but the problem is that I don't know at that time which version of Engine I need. I need a solution where I can define it later on. – Iamisti Aug 01 '16 at 15:10
  • after bootstrapping the application – Iamisti Aug 01 '16 at 15:44
  • Then provide it as factory. The instance will only be created when it is first injected. You can use http://stackoverflow.com/questions/37611549/how-to-pass-parameters-rendered-from-backend-to-angular2-bootstrap-method/37611614#37611614 to make Angular wait until the data is available. – Günter Zöchbauer Aug 01 '16 at 15:46
  • yes, but then I will loose the concept of having abstract classes and extended implementations. But the idea is not bad. – Iamisti Aug 01 '16 at 15:48
  • Not sure what you mean by "concept of having abstract classes and extended implementations" – Günter Zöchbauer Aug 01 '16 at 15:54
  • the abstract class 'Engine' has some methods implemented, and has others being abstract. This gives me a lot of encapsulation and nicer implementation, since in the specialised classes I have to do way less. – Iamisti Aug 01 '16 at 16:01
  • sure, but why do you think this doesn't work with the suggested approach? – Günter Zöchbauer Aug 01 '16 at 16:05
  • I don't see it as a clear solution. Maybe if you can sketch me something to show how did you think. That would be great. – Iamisti Aug 01 '16 at 16:24
  • Actually, I don't know what the problem is. I assume you want something like `provide(Engine, {useFactory: () => returnsomethingFromLoadedConfig()})` – Günter Zöchbauer Aug 01 '16 at 16:26
  • yes and by doing that I also want to ensure that all the injected Engines is going to have the same instance. But as I copied, I got an error message for that, since it's just an independent injector which I created. – Iamisti Aug 01 '16 at 16:33
  • Sorry I'm trying to understand you but it's hard if you don't provide an example for me. :) – Iamisti Aug 01 '16 at 16:33
  • I don't know what I should provide an example for when I don't understand what the problem is. If you update your question with more details what you try to accomplish I might be able to help. – Günter Zöchbauer Aug 01 '16 at 16:35
  • Actually, not at all."that's where I want to choose an implementation" I don't get where "where" is. " based on some conditions" what condition. You can use the factory function to use a condition `provide(Engine, {useFactory: () => condition ? new A() : new B()})`. Please provide a full example what you try to accomplish. Ideally with Plunker. – Günter Zöchbauer Aug 01 '16 at 16:45
  • sorry man, give me few minutes, I'll give you a much better example. – Iamisti Aug 01 '16 at 16:47
  • just updated with a plunkr example. It's not a full working example, it just represents what I want to achieve. – Iamisti Aug 01 '16 at 17:04
  • Sorry, I don't get it. I give up. – Günter Zöchbauer Aug 01 '16 at 17:07
  • no worries. I can't give a more clearer example. I think it's clear enough to get it. Maybe I'm wrong. – Iamisti Aug 01 '16 at 17:10
  • omg just saw that plunkr didn't save my changes and the example was completely different what I did. I'll recreate it tomorrow. You'll get it for sure if you'll see that. – Iamisti Aug 01 '16 at 20:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118848/discussion-between-gunter-zochbauer-and-iamisti). – Günter Zöchbauer Aug 01 '16 at 20:12