Angular 2.0 Dependency Injection between Services

910 views
Skip to first unread message

David Lesage

unread,
Apr 2, 2015, 8:06:53 PM4/2/15
to ang...@googlegroups.com
I was wondering if anyone knew of an example where an Angular 2.0 service is injected into another service, where by service I mean an exported class which is not a @Component, and as a result, does not have access to the @Component({services[SomeClass]}) provider information (as far as I can figure out -- I tried a few combinations of adding items like @Component to the class, but never found a combination that worked).

Right now, the error I receive is as follows: 
No provider for DispatcherService! (TodosComponent -> TodoStore -> DispatcherService)

My structural setup is:
  1. app.js gets TodosComponent from @Templates({directives[TodosComponent]})
  2. TodosComponent gets TodoStore from @Component({services:[TodoStore]}) and constructor(store: TodoStore)
  3. TodoStore does not get DispatcherService from import {DispatcherService} and constructor(dispatcher: DispatcherService) - the error above is thrown

Everything is functional when I remove "dispatcher: DispatcherService" from the constructor definition of TodoStore. I can even initialize a new DispatcherService() from inside the TodoService constructor, but that sort of defeats the purpose of sharing a single instance of the dispatcher. :) I can also "cheat" by injecting DispatcherService with a different class (such as TodoStore), but this feels incorrect to me since my TodosComponent technically isn't utilizing the DispatcherService yet. 

Any direction would be greatly appreciated! Especially since I know the spec is constantly fluctuating. I am using the version of Angular 2.0 from the Angular quickstart code, and I can post my full code, if necessary.

Sander Elias

unread,
Apr 3, 2015, 5:28:19 AM4/3/15
to ang...@googlegroups.com

Hi David,

You mean you want somethig like this:

export function threeStrikes (req:Request|string) {
  return this.http(req).retry(3);
}

@Inject(threeStrikes);
export class MyComponent {
  constructor(threeStrikes) {
    threeStrikes('[http://foo.bar](http://foo.bar/)').subscribe(onNext, onError);
  }
}

This is a Sample Jeff provided in another setting, but I think it is what you are asking, right?

Regards
Sander

David Lesage

unread,
Apr 3, 2015, 1:01:37 PM4/3/15
to ang...@googlegroups.com
Absolutely, that looks perfect. Is that syntax functional, or just proposed? I'm wondering if I need a newer version of Angular2 than what is included with the quickstart to get that to work.

I'm currently not having any luck with the following:

import {DispatcherService} from 'services/DispatcherService';
import {Inject} from 'angular2/di';

@Inject(DispatcherService) // had to remove the semicolon, was getting an 'Unsupported annotated expression' error
export class TodoStore {
  constructor
(dispatcher: DispatcherService) {}
}

I am still receiving the No provider for DispatcherService! (TodosComponent -> TodoStore -> DispatcherService) error.

Milan Pevec

unread,
Apr 23, 2015, 10:42:25 AM4/23/15
to ang...@googlegroups.com
Hi David,

did you maybe find the solution ?

Regards,
Milan

David Lesage

unread,
Apr 23, 2015, 12:50:58 PM4/23/15
to ang...@googlegroups.com
Yes and no -- My next step was to update the Angular2 code by grabbing it off of github, followed by grabbing all of the dependencies myself (SystemJS, Traceur, etc) and starting from scratch. I eventually got it into a state where all of the injection mostly worked, but I was getting an issue where multiple injections of the same type in different locations were not the same instance, and I was getting some unexpected behavior while trying to create a local cache/store/whatever you want to call it. That was either a bug (unlikely), a user-error (seems more likely), or just me misunderstanding the dependency injection expectations in Angular2.

At that point I broke it down further, and I grabbed the di.js code directly from Angular's github and ran with that separately to make sure my expectations weren't incorrect -- but that worked exactly as I expected. Phenomenally, in fact -- I loved it. They have better examples than anything I could give, though.

I suppose the TL;DR is -- No, I never got it fully working. Are you seeing the same error I was?

Milan Pevec

unread,
Apr 24, 2015, 4:34:02 AM4/24/15
to ang...@googlegroups.com
Thank you for the answer and yes I see the same error..

Milan

Milan Pevec

unread,
Apr 24, 2015, 6:15:38 AM4/24/15
to ang...@googlegroups.com
So this should work or did I miss something ?


Milan

David Lesage

unread,
Apr 25, 2015, 1:57:33 AM4/25/15
to ang...@googlegroups.com

I took one of the templates from the angular website and extended it -- One thing to note (and I'm not sure if this is intentional or not, doesn't seem to be necessary with di.js), I had to include @Component injectables as [Service, AnotherService], instead of just the parent dependency of AnotherService. Try it for yourself -- if I remove Service from that array, the whole thing breaks for me.

Whether that's intentional behavior or not, I'm not sure, but that's what I saw earlier with the dependency injection in the quickstart code as well.

--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/PPl6jxL5zps/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.

Milan Pevec

unread,
Apr 26, 2015, 7:29:28 AM4/26/15
to ang...@googlegroups.com
Thank you, it's a lit a bit strange to include everything in the @Component injectables, but its working like this.

Milan

David Lesage

unread,
Apr 26, 2015, 2:52:24 PM4/26/15
to ang...@googlegroups.com
I agree -- and I'm not convinced that it's not a bug. I feel like di.js should be able to resolve those child dependencies without needing to have them injected. I've seen it work that way, at any rate. You can just run injector.get(TopLevelComponent) and all child level dependencies can be resolved (either through typescript or explicit @Inject calls).

Side note (somewhat related), take a look at this: http://plnkr.co/edit/UyNe7a4wD3OWXGTyWlAI?p=preview

Note that AnotherService has its id incremented multiple times, which I believe indicates that the dependency injection is creating a new instance each time.
Now remove AnotherService from NameComponent's injectables (line 36). I am seeing that works as I had expected -- a single instance of a service injected across all components.

And a second side note (not really related), I just realized I don't know how to get information from the parent DisplayComponent into the child NameComponent. Any thoughts? I know Angular1.x would just slap the data on the child directive's $scope. I played around with the (load) event for a bit, but wasn't having any real luck (and I'm not sure if that's the best way of going about that, anyways).

Milan Pevec

unread,
Apr 27, 2015, 8:44:59 AM4/27/15
to ang...@googlegroups.com
For singletons I will use (for now) this solution: http://twofuckingdevelopers.com/2015/04/angular-2-singleton-service/ 

About requiring parent component for communication I did not try it but maybe this could help: http://unobfuscated.blogspot.be/2015/03/posts-from-edge-injecting-parents-into.html

Milan

Georgios Diamantopoulos

unread,
Jun 17, 2015, 4:02:19 AM6/17/15
to ang...@googlegroups.com
Still seeing this in alpha 26. Any news since this last post?

David Lesage

unread,
Jun 17, 2015, 12:18:58 PM6/17/15
to ang...@googlegroups.com
Last I heard, this was working as intended. Still feels strange to me, though.
Reply all
Reply to author
Forward
0 new messages