Karl Johan Vallner
Karl Johan Vallner

Reputation: 4300

Angular2 import and declare global service from submodule

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?

Upvotes: 0

Views: 2451

Answers (3)

dppower
dppower

Reputation: 170

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: []
        };
    };
};

Upvotes: 2

AngularChef
AngularChef

Reputation: 14087

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.

Upvotes: 0

Merschi
Merschi

Reputation: 56

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.

Upvotes: 0

Related Questions