Angular 2 – how do providers actually work?

I’ve been going through the “Heroes” tutorial on official Angular 2 page and when I came to routing, a couple of things didn’t make sense. It’s about providers.

The part in question is represented as follows. My main component looks like this:

/* app.components */
import {Component} from 'angular2/core';
import {HeroesComponent} from './heroes.component';
import {HeroService} from './hero.service';

@Component({
    selector: 'my-app',
    template: `
        <h1>{{title}}</h1>
        <my-heroes></my-heroes>
    `
    directives: [HeroesComponent],
    providers: [HeroService]

})
export class AppComponent {
    title = 'Tour of Heroes';
    constructor(private _heroService: HeroService) {}
}

and the heroes components looks like this:

/* heroes.component */
import {Component} from 'angular2/core';
import {Hero} from './hero';
import {HeroDetailComponent} from './hero-detail.component';
import {HeroService} from './hero.service';
import {OnInit} from 'angular2/core';

@Component({
    selector: 'my-heroes',
    directives: [HeroDetailComponent],
    template: `
        <h2>My Heroes</h2>
        <ul class="heroes">
            <li *ngFor="#hero of heroes" [class.selected] = "hero === selectedHero" (click)="onSelect(hero)">
                <span class="badge"> {{hero.id}} </span> {{hero.name}}
            </li>
        </ul>
        <my-hero-detail [hero]="selectedHero"></my-hero-detail>
        `
})
export class HeroesComponent implements OnInit {
    heroes: Hero[];
    selectedHero: Hero;
    ngOnInit() {
        this.getHeroes();
    }
    constructor(private _heroService: HeroService) {    }

    getHeroes() {
        this._heroService.getHeroes().then(heroes => this.heroes = heroes);
    }

    onSelect(hero: Hero) {
        this.selectedHero = hero;
    }

}

OK, so my question: in order for this to work, I need to import import {HeroService} from './hero.service'; in both files. However, providers: [HeroService] is only a part of the @Component of app.components. I needn’t write this piece of code in heroes.component. How does the heroes.component know which provider to pick? Is it inherited from app.components? And if so, why did I have to write this in both files: import {HeroService} from './hero.service';? Why not just in app.components? Both classes also have the same constructor. I don’t know what’s going on here, so thanks in advance for any explanation.

4
Leave a Reply

avatar
4 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

Injectors are hierarchical. In bootstrap() the root provider is initialized, then for each component another child-injector is created which leads to a structure that mimics your components in the DOM. When Angular instantiates a class (service, component, pipe, …) it requests an instance of DI and DI tries to resolve the constructor parameters as well. This is recursively done until no further dependencies are necessary to resolve, then the instance is returned. An instance is requested from the closest injector. If the injector doesn’t have a provider for a type (or other key like string or OpaqueToken) the request is… Read more »

Jason
Guest

This is linked to the “hierarchical injectors” feature of Angular2. These injectors are linked to components and follow the same tree.

The injector of a child component is a sub injector of the parent component. If the provider isn’t found into the current injector, it will be looked for into the parent one…

See this question for more details:

Jason
Guest

Yes, it is inherited and injectors are hierarchical. Check this blog post and official documentation.

Jason
Guest

After studied some documentation of Angular-2 I shared my knowledge about dependency-injection and providers that may can help someone. The Dependency injection is hierarchical and Dependency injection is an important application design pattern. Angular has its own dependency injection framework, and we really can’t build an Angular application without it. Dependencies are singletons within the scope of an injector. In our example, a single HeroService instance is shared among the AppComponent and its HeroComponentchildren. In your example the AppComponent is the root component of the Heroes feature area. It governs all the child components of this area. Yur HeroService may… Read more »