Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid declaring all services in the bootstrap() function?

Tags:

angular

So based on my previous question: Angular2 "Services" how to @inject one service into another (singletons)

For which I have an answer now a new question dawned on me. And that is due to the fact that so far everywhere I look all the services are included within the bootstrap method. Things like Pascal Precht's blog post also indicate this: http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

But to me this comes across (in comparison with Angular1) as really ugly coding. For this to work in those instances I would have to include all my services within the app component (Angular1 config module). While the strength should come from having each Class "Module" take care of getting its own dependencies (providers) that are singletons throughout the application.

Now my question is:

Is it possible to have classes specify their own dependencies while the dependency remains a singleton for all other classes that require the same one as well. Something like:

app.ts

@Component({
  selector: 'app',
  providers: [
    TeamCollection
  ]
})
@View({
  template: '{{name}}'
})
class TestApp {
  name: string;
  teamCollection: TeamCollection;
  constructor(@Inject(TeamCollection) teamCollection: TeamCollection){
    this.name = 'Angular2';
    this.teamCollection = teamCollection;
  }
}

export function main() {
  bootstrap(TestApp);  
}

team.ts

@Injectable()
export class TeamCollection extends BaseCollection {
    playerCollection: PlayerCollection;
    constructor(playerCollection: PlayerCollection) {
        super();
        this.playerCollection = playerCollection;
    }

    create(data: Object): TeamModel {
        return new TeamModel(data);
    }
}

player.ts

@Injectable()
export class PlayerCollection extends BaseCollection {
    create(data: Object): PlayerModel {
        return new PlayerModel(data);
    }
}

Without having me both include the TeamCollection and the PlayerCollection within the providers array of the app component. And instead having the Teamcollection inject a PlayerCollection singleton instance into its constructor upon creation of the TeamCollection singleton instance through the App component providers array.

To me that feels really off, but if this is the way of Angular2 I will just have to learn to adjust to it.

Edit: I wanted to explain this further by illustrating the fact that if I want a service that is shared by all components within the application I have to add it to the bootstrap method. Which in a project that previously had maybe 50+ services becomes incredibly ugly (if it has to all be in the bootstrap function).

Another thing: It would be really inconsistent as well seeing the @RouteConfig is something that looks into the sub-classes when you specify a route like abc/... Meaning the component ABC can have its own @RouteConfig etc. Which is a great change compared the Angular1 in which we had to specify everything within the config().

Edit2: See @alexpods comment: https://github.com/angular/angular/issues/5063#issuecomment-154753852

And @EricMartinez comment below. To see the correct way to handle modularity in angular2.

like image 291
N.Schipper Avatar asked Nov 09 '22 02:11

N.Schipper


1 Answers

You can export services as a single token and provide them as collection at bootstrap() like

a.js

export const MODULE_A: any[] = [Service1, Service2, Service3];

b.js

export const MODULE_B: any[] = [Service3, Service4, Service5];

c.js

import {MODULE_A} from 'a.js';    
import {MODULE_B} from 'b.js';

export const MODULE_C: any[] = [MODULE_A, Module_B, Service6];

main.js

import {MODULE_C} from 'c.js';

bootstrap(AppComponent, [MODULE_C];

This is common practice in Angular2, like ROUTER_PROVIDERS, MD_CARD_PROVIDERS, ...

like image 184
Günter Zöchbauer Avatar answered Nov 15 '22 07:11

Günter Zöchbauer