0

I have an interesting question. I have 2 modules. app.module.ts (AppModule) and listings.module.ts (ListingsModule). ListingsModule has a service, let us call it service A. A needs to be a singleton global service, meaning that all of the other components and services need to be able to interact with the same A.

For this I firstly tried declaring A as a provider in ListingsModule, but this did not work as expected as it was only being declared a singleton for use for components and services under ListingsModule, but I also needed to use it under other modules and under AppModule. I thus concluded that I need to export this service from ListingsModule and import and provide this under AppModule, but this did not work as expected.

A is ListingsStoreService.

//Stores
import { ListingsStoreService }             from './shared/listings-store.service';

//Modules
import { SharedModule }                                 from './../shared/shared.module';
import { HeaderModule }                                 from './../header/header.module';

@NgModule({
    imports: [
        SharedModule,
        HeaderModule,
        ListingsRoutingModule
    ],
    declarations: [
        ListingsComponent
    ],
    exports: [
        ListingsStoreService
    ],
    providers: [        ]
})
export class ListingsModule {
}

The following code asks me to declare or import ListingsStoreService, for it to be exportable. If I declare ListingsStoreService then it gives me another error. I can apparently only provide this service.

What is the right approach here? How do I make this work?

Karl Johan Vallner
  • 3,051
  • 2
  • 28
  • 40
  • Add the providers to `forRoot()` https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root and import the `SharedModule.forRoot()` in `AppModule`s `imports: []` – Günter Zöchbauer Feb 06 '17 at 09:15

3 Answers3

1

What angular does with some of it's modules (e.g. RouterModule) is to allow for the creation of two versions of the same module, via static functions called "forRoot" and "forChild", by convention. "forRoot" could contain a global service, such as "ListingsStoreService" in it's provider array, and "forChild" would omit it. Then you could call "ListingsModule.forRoot()" in the AppModule imports array, and call "ListingsModule.forChild()" everywhere else you need the "ListingsModule".

@NgModule({
imports: [
    SharedModule,
    HeaderModule,
    ListingsRoutingModule
],
declarations: [
    ListingsComponent
]
})
export class ListingsModule {
    static forRoot() : ModuleWithProviders {
        return {
            ngModule: ListingsModule,
            providers: [ ListingsStoreService ]
        };    
    };

    static forChild() : ModuleWithProviders {
        return {
             ngModule: ListingsModule,
             providers: []
        };
    };
};
dppower
  • 150
  • 9
0

Your ListingsStoreService have to be imported in

imports: [
    SharedModule,
    HeaderModule,
    ListingsRoutingModule,
    ListingsStoreService
],

I think this is your problem. Can you try this? I've had written a comment, but i need 50 reputation for that ... so here is an answer where i don't know 100% if it works.

Merschi
  • 56
  • 1
  • 5
  • I'm sorry, but importing is for NgModules. ListingsStoreService is a service. This answer will not work. – Karl Johan Vallner Feb 06 '17 at 09:25
  • A yes, i see. Is it possible, that you simply use the wrong directory for importing? In the first import you use ./shared/listings-store.service and in the second you use ./../shared/shared.module – Merschi Feb 06 '17 at 09:38
0

It should work with no special configuration. Services have a global scope by default (as long as the module where they are declared is eagerly loaded). Your initial configuration (that you described in your question) should work.

Declare your service in the providers of ListingsModule:

@NgModule({
  providers: [ ListingsStoreService ]
})
export class ListingsModule {
}

Then import ListingsModule in AppModule:

@NgModule({
  imports: [ ListingsModule ]
})
export class AppModule {
}

NB. ListingsModule must be eagerly loaded, NOT lazy-loaded. Your question doesn't say how ListingsModule is loaded in your case.

AngularChef
  • 12,435
  • 6
  • 48
  • 64