2
votes

From Angular documentation:

Create a "top component" that acts as the root for all of the module's components. Add the custom HttpBackend provider to the top component's providers list rather than the module's providers. Recall that Angular creates a child injector for each component instance and populates the injector with the component's own providers.

When a child of this component asks for the HttpBackend service, Angular provides the local HttpBackend service, not the version provided in the application root injector. Child components make proper http requests no matter what other modules do to HttpBackend.

Be sure to create module components as children of this module's top component.

If we open source files for documentation of Hierarchical Dependency Injectors, we can see that ACarComponent, BCarComponent and CCarComponent creates three different instances of CarService, CarService2 and CarService3.

But how I can to get CarService from parent DI for child component BCarComponent if I have also provide CarService on module level?

1
But how I can to get parent DI from child component - what do you mean? what is your use case? do you define providers on components or modules? - Max Koretskyi
@AngularInDepth.com, as you can see on quote - I defined provider on "top component' and I want get DI from this point for inner child component. - ktretyak
do you want to skip all intermediate component injectors? why are you not defining the provider at the module level as Suren recommends? - Max Koretskyi
@AngularInDepth.com, I learn documentation (see link above) and I want to know how I can to get singleton from "top component", not from module level. - ktretyak
you can't do that with available public API - Max Koretskyi

1 Answers

4
votes

If you will not give a provider for CCarComponent, it will go and try to get that provider instance from his parent component and so on.

Let's see an example.

@Component({
   selector: 'a-car-comp',
   template: '<div><b-car-comp></b-car-comp></div>',
   providers: [CarService]
})
class ACarComponent { 
    constructor(private carService: CarService) {}
}


@Component({
   selector: 'b-car-comp',
   template: '<div><c-car-comp></c-car-comp></div>'
})
class BCarComponent { 
    constructor(private carService: CarService) {}
}

@Component({
   selector: 'c-car-comp',
   template: '<div></div>'
})
class CCarComponent { 
    constructor(private carService: CarService) {}
}

Here I inject an instance of CarService into A, B and C Car components. In B and C components I have not provide their own CarService (providers list is empty) so it goes to his parent component (which uses it in his template) and get the same instance.

Each component which wants an instance of a service first tries to find in it's own providers, if not found, goes to upper component and tries to find there and so till to the root component (here upper component is that one which uses current component in it's template). If it is not found there too, Angular throws an

Error: No Provider found for YourService