angulartypescriptdependency-injectionangular2-di

Angular 2 Hierarchical Dependency Injection - Declaring root provider's dependencies outside of root?


(Note I am using Angular 2 RC5)

For simplicity, I have an app like so:

app.module.ts

@NgModule({
    providers: [
        RootService
    ],
    entryComponents: [AppComponent],
    bootstrap: [AppComponent]
})

export class AppModule {}

root.service.ts

import Dependency1 from './somewhere'
import Dependency2 from './somewhere-else'

@Component({
    providers: [Dependency1, Dependency2]
})

@Injectable()
export class RootService {
    constructor(
        private dep1: Dependency1, 
        private dep2: Dependency2
    ) {...}
}

An example of a dependency is:

dependency1.ts

@Injectable()
    export class Dependency1{
    public doGroundbreakingSciencyStuff() {...}
}

My question is: Why, with the above, am I greeted with an error saying: No provider for PouchSync!.

I can solve the problem by adding Dependency1 and Dependency2 to the providers array in app.module.ts like so:

app.module.ts (fixed)

@NgModule({
    providers: [
        RootService,
        Dependency1,
        Dependency2
    ],
    entryComponents: [AppComponent],
    bootstrap: [AppComponent]
})

export class AppModule {}

This just seems very ugly. Only RootService need to know about these dependencies. Am I doing something wrong here? Or can someone explain why it has to be this way? Surely, when injecting RootService, the injector can see that it's dependent on Dependency1 and Dependency2 and hence must inject those too, and hence they'll also be application wide singletons.


Solution

  • Services are not components, so they can't have @Component decorator (which means - it is impossible to add providers array for service class). Conclusion? This code is wrong:

    @Component({
        providers: [PouchSync, PouchArraySync]
    })
    
    @Injectable()
    export class RootService {
        constructor(
            private dep1: Dependency1, 
            private dep2: Dependency2
        ) {...}
    }
    

    But your second example is made in angular 2 way.

    You wrote that only RootService need to know about dependencies. So if these dependencies are not reusable objects, which should be injected in few pieces of your application, but only available in this class(!) - you should just create instances of them inside your service.