0

I have used the following approach several times in my projects in order to pass data from one component to another. However, this time I have 2 component: parent (in AppModule) and sidebar (in CoreModule) components and I am trying to pass data from parent to sidebar on a dropdown change. However, it does not work and the subscribe method on the sidebar component (in the example child component) is not triggered except from initial loading. Does being on different modules cause this problem? Or any other issue about that?

Here is the DEMO.

Update:

Here is my module relationship:

parent.module:

imports: [
  SharedModule
],
providers: []

child.module:

imports: [
  SharedModule
],
providers: []

shared.module:

providers: [
    DataService
]

When I update as shown above, it still does not work. However, if I move DataService in the providers field from shared.module to app.module it works. But I think it should work when it is only in shared.module as shown above. Why?

  • Does this answer your question? [How to share service between two modules - @NgModule in angular not between to components?](https://stackoverflow.com/questions/40089316/how-to-share-service-between-two-modules-ngmodule-in-angular-not-between-to-c) – Michael D Feb 10 '21 at 13:56
  • @MichaelD Not exactly, please see my update. The problem is related to modules. –  Feb 10 '21 at 14:55
  • Since the modules import 'their own version' of the shared module, both have an instance of the service. – Gunnar B. Feb 10 '21 at 14:56
  • So, what is the proper way for this scene? Should I move the `DataService` from shared.module to app.module's providers section? Is it good habit to use service in AppModule's providers section? –  Feb 10 '21 at 14:59
  • @GunnarB. Do you mean that it should work with the state in my Update? –  Feb 11 '21 at 12:30
  • 1
    The only way to make a service a singleton (meaning a single instance for the whole application) is by providing it in the root i.e. the app module. Providing it in sub modules is basically the same as providing it directly in a component which will create an instance for the specific component. The whole application is build like a tree, one branch doesn't know about any other since stuff only goes away from the root. – Gunnar B. Feb 11 '21 at 18:18
  • Thanks a lot for this good explanations. –  Feb 11 '21 at 19:24

2 Answers2

0

I believe the issue is related to the provider instance in each module, have you tried adding only 1 provider to the top parent module and see the result?

Using components vs services from other modules There is an important distinction between using another module's component and using a service from another module. Import modules when you want to use directives, pipes, and components. Importing a module with services means that you will have a new instance of that service, which typically is not what you need (typically one wants to reuse an existing service). Use module imports to control service instantiation.

The most common way to get a hold of shared services is through Angular dependency injection, rather than through the module system (importing a module will result in a new service instance, which is not a typical usage).

To read about sharing services, see Providers. https://angular.io/guide/sharing-ngmodules

Basically, when you import a new module, a new instance of provider is created by each import, so the injection is different, if you need the data to be same for both, you need to handle the provider in the AppModule in this case

Breno Prata
  • 412
  • 3
  • 7
  • **Exactly!..** But, why? See my update please and let me know why it is not working on shared service? –  Feb 11 '21 at 12:29
  • By the way, for now voted up ;) –  Feb 11 '21 at 12:29
  • I believe the behaviour you need is not supported, here is a quote from the documentation: – Breno Prata Feb 12 '21 at 13:06
  • **1.** Thanks a lot. In this scene, could we say that if we need to share service between different modules, we should move this service to only `app.module`? –  Feb 12 '21 at 19:50
  • **2.** And what about `providedIn: 'platform'` ? Should I still need to use it if I move the shared service to `app.module`? –  Feb 12 '21 at 19:52
0

Usually you can attach all your services to the root Injector. So instead of providing services to modules or components, set provideIn: 'root':

@Injectable({provideIn: 'root'}) 
export class DataService { ... }

(and don't forget to remove it from providers arrays).

My best guest why you experience this issue is because your modules are loaded lazily, what causes them to have their own Injector what finally results in multiple instances of your service.

So either use my suggested way, or read more about forRoot() and forChild() if you need to keep your service in module's providers array.

Julius
  • 9,779
  • 10
  • 29
  • 71
  • Thanks a lot, voted up. You may also share your ideas about my Update in the question. –  Feb 11 '21 at 12:31
  • To do that I need more context, preferably a demo with the issue you described – Julius Feb 11 '21 at 12:46