When import services, should I import them in "imports" array or providers array in NgModule?

Issue

From Angular Doc, the def about imports in NgModule is:

Specifies a list of modules whose exported directives/pipes should be available to templates in this module.

And providers:

Defines the set of injectable objects that are available in the injector of this module.

So here is the question, when I want to use a 3rd service packed in a 3rd module, should I import the module in imports, or register the particular service, in providers?

Solution

In general, all services added to the providers array of any module are application-wide singletons – meaning they are added to the root injector automatically. There is no need to explicitly add them to the providers array of your AppModule.

That means that when you import a module (or another module imports a module) that has the providers array populated, the services they provide can be injected into any injectable constructor – regardless of where it is. Just import the service, and add it to an injectable constructor.

Now, I say “in general” because for the most part that’s true. The only case where it is different is when the module is a lazy loaded module (i.e. loading lazy-loaded routes). Lazy-loaded modules have their own root scope. If you treat that as the exception, it all makes sense.

So to answer your question:

  1. Prefer module.forRoot() if it has such a method. This returns a module with services, which will get bootstrapped with the root injector.

    @NgModule({
        // forRoot ensures that services are added to root injector
        imports: [ThirdPartyModule.forRoot()],
        exports: [],
        declarations: [...],
        providers: [],
    })
    export class AppModule{ }
    
  2. If there is no “forRoot” method, then just import the module into AppModule. Likely, the module has services intended to be registered with the root injector.

    @NgModule({
        imports: [ThirdPartyModule],
        exports: [],
        declarations: [...],
        providers: [],
    })
    export class AppModule{ }
    
  3. If you need to import the module from a FeatureModule (or a SharedModule) because you want to leverage the components, directives, and pipes contained within it, you should use the forChild() method if it has one.

    @NgModule({
        // does not include any services. You still need to import
        // .forRoot() in the AppModule
        imports: [ThirdPartyModule.forChild()],
        exports: [],
        declarations: [...],
        providers: [],
    })
    export class FeatureModule { }
    
  4. If the author of the module has not provided a forRoot() or forChild() method, it may be it was never intended to be imported by any module other than the AppModule.

  5. The author of the module may have decided to include services in the module, but by default chose not to add it to the providers array. In that case its up to you to add it to a providers array of a module (services will have root scope), or add it to a component’s providers array (services will have component scope).

Answered By – pixelbits

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published