Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency in Angular importing and exporting of module

Tags:

angular

I have a SharedModule that provides and export a service and I would like to import that service in a component of another module by referring to the shared module typescript file instead of the service typescript file. But the build is failing as somehow the exported service is not detected in the other component.

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [
      ...
    ],
  providers : [
    LookupService
  ],
  exports : [
    LookupService
  ]
})
export class SharedModule { }

Then it is imported in another feature module

  @NgModule({
  imports: [
    CommonModule,
    SharedModule,  
  ],
  declarations: [
    LegalTermComponent
  ],
  providers : [LegalTermService]
})
export class LegalTermModule { }

And in LegalTermComponent which is in LegalTermModule I want to import

import { LookupService } from '../shared/shared.module';

This is where build complains ....

   ERROR in src/app/legal-term/legal-term.component.ts(11,10): error TS2305: Module '".../src/app/shared/shared.module"' has no exported member 'LookupService'.

I cannot figure why it says there is no exported member when clearly the shared module exports it. Can anyone please tell me the correct way to do this? (the import works fine if I refer directly to lookup.service.ts )

Thanks! Anand

like image 892
Anand Avatar asked Nov 18 '25 11:11

Anand


1 Answers

Services are singletons with root scope. If you want to make sure that the services you provide are singletons at the app level, then you need to import the module with services in the AppModule. For the FeatureModule, you want to import the SharedModule without any services - otherwise, it can create its own copy of services which overrides the app-level services (i.e. lazy loaded modules) - that is not likely what you want.

To do this, you should follow the convention of creating two static methods from the shared module: one method returns the module with services, and another method returns the module without services.

The one without services should only be imported by the FeatureModule. The one with the services should be imported by the AppModule.

FYI, that is why the forRoot (with services) and forChild (without services) convention exists.

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [
      ... (shared components)
    ],
  providers : [

  ],
  exports : [
    ... (shared components)
  ]
})
export class SharedModule { 
     // intended to be imported by AppModule
     static forRoot(): ModuleWithProviders {
         return  {
             ngModule: SharedModule, 
             providers: [LookupService]
         }
     }

     // intended to be imported by FeatureModules
     static forChild(): ModuleWithProviders {
         return {
             ngModule: SharedModule, 
             providers: []
         }
     }
}

Feature Modules

@NgModule({
  imports: [
    CommonModule,
    SharedModule.forChild(),  //without services
  ],
  declarations: [
    LegalTermComponent
  ],
  providers : [LegalTermService]
})
export class LegalTermModule { }

App Module

@NgModule({
  imports: [
    SharedModule.forRoot(), //with services  
  ],
  declarations: [
    ...
  ],
  providers : [
    ...
  ]
})
export class AppModule{ }

To be clear, providers normally have application-wide root scope regardless of which module its provided in. That is because there is no module-scoping mechanism for providers like there is for components. The only exception to this are lazy-loaded modules - which introduces their own child-root scope.

like image 172
pixelbits Avatar answered Nov 20 '25 04:11

pixelbits



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!