How do I Access AppModule Module imports from Lazy-loaded Modules?

Viewed 660

How do I Access AppModule imports from Lazy-loaded Modules ?

My Angular10 App imports AngularMaterial and NXTranslate Modules in to the AppModule. NxTranslate calls an ApiService to get a large Lookup object of thousands of translations. This is translated at the initial loading of the AppModule.

The App has multiple lazy-loaded routes that also need to use the AnagularMaterial and NXTranslate Modules in their features.

If I use a SharedModule to load the Modules then the ApiService is called multiple times. This is obviously not good. It should only call the ApiService & AngularMaterial once and be available for all modules.

How do I resolve this? I am struggling. Thanks.


Update (sorry for the long post) This is the NXTranslate implementation - it uses a custom class.

import { environment } from './../../../../environments/environment';
import { OSCITranslateService } from './translate.service';
import { NgModule, Injector } from '@angular/core';
import { CommonModule } from '@angular/common';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';

export class CustomLoader implements TranslateLoader {

localeResourcesUrl =
`${environment.baseUrl}${environment.apiUrl.localeResources}`;

constructor(private http: HttpClient) {}

getTranslation(lang: string): Observable<any> {
let  options;
const uri = `${this.localeResourcesUrl}${options && options.key ? 
'/' + options.key : ''}`;

let mapped = this.http.get(uri).pipe(
  map((response: any) => {
    let localeData = {};
    let languageCode = response?.languageVariantCode;

    response.resources.forEach(item => {
      localeData[item.keyName] = item.keyValue;
    });
    return localeData;
  })
);
return mapped;
}
}

@NgModule({
declarations: [],
imports: [
CommonModule,
HttpClientModule,
TranslateModule.forRoot({
    loader: {
        provide: TranslateLoader,
        useClass: CustomLoader,
        deps: [HttpClient]
    }
})
],
exports: [ TranslateModule ]
})
export class NxTranslateModule { 

constructor(private http: HttpClient) {
}
}

This is the sharedRootModule that imports the AngularMaterial & NXTranslate

import { SharedModule } from './shared.module';
import { NgModule, ModuleWithProviders } from '@angular/core';

@NgModule({
})
export class SharedRootModule {

  static forRoot(): ModuleWithProviders<SharedModule> {
    return {
      ngModule: SharedModule
    };
  }
}

In AppModule SharedRootModule is imported

...
@NgModule({
  declarations: [
     AppComponent
  ],
  imports: [
    ...
    SharedRootModule.forRoot()
  ],
  exports: [
    ...
    SharedRootModule
  ]
....
1 Answers

Are you concerned about the multiple ApiService instances you might end up with? Provide the ApiService within AppModule only, or even better, use the providedIn property right in your service's decorator so it gets injected at application level. (https://angular.io/api/core/Injectable#providedIn)

I would just use a SharedModule that exports the mentioned lazy loaded modules.

Related