How would I go about injecting one service into another? Let's for example say I have a Collection that requires another Collection (TeamCollection => PlayerCollection). Currently I just create two separate Collections and use something like:
import {PlayerCollection} from "<<folder>>/player";
But this requires me to write my own singleton getInstance code within Typescript for each and every service that I want to be a singleton instance.
What is the correct way to do this? I want to have both singletons within my Components and be able to @Inject one service into another using the constructor syntax, without creating a new instance of the singletons.
class TeamCollection { constructor(@Inject(PlayerCollection): PlayerCollection) {} }
You can inject an Angular service in a component, service, directive etc by specifying the service and its type in a component's constructor. Note that injecting a service through a class constructor is, in general, tree-shakable.
Angular provides the ability for you to inject a service into a component to give that component access to the service. The @Injectable() decorator defines a class as a service in Angular and allows Angular to inject it into a component as a dependency.
So after re-reading this excellent post by Pascal Precht: http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html
And seeing him comment on: http://twofuckingdevelopers.com/2015/04/angular-2-singleton-service/
"Everything injected using Angular 2’s DI is already a Singleton. No need for such a service"
I went testing, and what I now found has both answered my question and made me even more confused about the topic of DI in angular2.
See the following code:
team.ts
import {BaseCollection, BaseModel} from "./base"; import {PlayerCollection} from './player'; import {Injectable, Inject} from "angular2/angular2"; @Injectable() export class TeamCollection extends BaseCollection { playerCollection: PlayerCollection; constructor(@Inject(PlayerCollection) playerCollection: PlayerCollection) { super(); this.playerCollection = playerCollection; } create(data: Object): TeamModel { return new TeamModel(data); } }
player.ts
import {BaseCollection, BaseModel} from "./base"; import {Injectable} from "angular2/angular2"; @Injectable() export class PlayerCollection extends BaseCollection { create(data: Object): PlayerModel { return new PlayerModel(data); } }
team.spec.ts
/// <reference path="../../typings.d.ts" /> //VERY IMPORTANT TO ALWAYS LOAD THESE import 'zone.js'; import 'reflect-metadata'; import 'es6-shim'; import {TeamModel, TeamCollection} from "../../app/model/team"; import {PlayerCollection} from "../../app/model/player"; import {Inject, Injector} from "angular2/angular2"; describe('TeamCollection', () => { var teamCollection: TeamCollection; var playerCollection: PlayerCollection; beforeEach(() => { var injector = Injector.resolveAndCreate([ TeamCollection, PlayerCollection ]); teamCollection = injector.get(TeamCollection); var injectorT = Injector.resolveAndCreate([ PlayerCollection ]); playerCollection = injector.get(PlayerCollection); }); it('should have a singleton PlayerCollection shared between all classes within the application', () => { console.log(teamCollection.playerCollection.uuId); console.log(playerCollection.uuId); }); });
As long as it was the same Injector (var injector
) that created both they share the same uuID Though when I use a second injector (var injectorT
) the UUIDs are different meaning a new instance is created of the playerCollection.
Now my question would be. If I use the component providers syntax:
@Component({ selector: 'app', providers: [TeamCollection] }) @Component({ selector: 'player-list', providers: [PlayerCollection] })
Would both share the same player collection or would both create a new instance?
Edit: They do as long as they are created through the bootstrap(.., [ServiceA,ServiceB])
method.
Thanks to pascal precht http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html
I found that another way of having a singleton service is by creating the singleton pattern with a getInstance() method that calls the constructor, then you don't inject your service to the component constructor, but just reference it as a static class. You can check sample code in here:
Access key data across entire app in Angular 2 & Ionic 2
Look for my answer, I think its the second in the page. If it works for you I would appreciate if you could up-vote it. Thanks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With