5

I have an ErrorModule (eager) configured as follows:

export const CONFIG = new InjectionToken<ErrorConfig[]>('Module errors configuration.');


@NgModule({
  imports: [... ]
})
export class ErrorModule {
  static forRoot(config: ErrorConfig): ModuleWithProviders {
    return {
      ngModule: ErrorModule,
      providers: [
        ErrorService,
        { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
        { provide: CONFIG, useValue: config, multi: true }
      ]
    };
  }

  static forChild(config: ErrorConfig): ModuleWithProviders {
    return {
      ngModule: ErrorModule,
      providers: [
        { provide: CONFIG, useValue: config, multi: true }
      ]
    };
  }
}

Core module then imports ErrorModule as follows:

@NgModule({
  imports: [
    ErrorModule.forRoot(ERROR_CONFIG)
  ], ...

Lazy loaded child feature module:

@NgModule({
  imports: [
    ErrorModule.forChild(ERROR_CONFIG_CHILD)
  ], ...

I would like to see both configurations ERROR_CONFIG and ERROR_CONFIG_CHILD injected into ErrorService defined in ErrorModule:

@Injectable
export class ErrorService {
    constructor(@Inject(CONFIG) private readonly errorConfigs: ErrorConfig[])
}

But the service's errorConfigs (in constructor) contains only CONFIG defined in core.module - the one defined in forRoot() function (An array with one element).

Lazy feature module has been loaded and initialized and the ErrorModule.forChild(...) invoked

It kind of makes sense that the ErrorService has been constructed in time when only core module's CONFIG injection token was available - the feature module has not beeen loaded yet.

I have also tried to import the CONFIG using Angular Injector outside of constructor (method in ErrorService) and the result was same.

const configs: any[] = injector.get(CONFIG); // returns only root CONFIG

So my question is: Is it possible to somehow access a provider provided by a lazy module in app module? (Access it in app's root injector?)

7
  • Did you find an alternative? I'd like to implement basically the same thing, pluggable features. This does not seem to be feasible through DI at a first glance, and I'm not really surprised nor deceived. But it's too bad that this gonna end up with a singleton service you can register to (in a non-declarative or IoC way). Commented Feb 10, 2019 at 21:51
  • @MorganTouvereyQuilling see my answer bellow - an alterative. Commented Feb 11, 2019 at 8:31
  • 1
    @Felix @MorganTouvereyQuilling Do you guys think we should implement this use case like in @angular/router module? I still haven't unraveled the "black magic" done in the router config loader though. 🤷 • router modulerouter config loader Commented May 28, 2019 at 7:51
  • Did you ever find an 'angular-way' solution for this? I basically need the same thing Commented Nov 22, 2019 at 15:43
  • @devqon I used the solution below. I have no angular-way solution. Commented Nov 23, 2019 at 20:38

1 Answer 1

2

I ended up with a solution, that uses ErrorService defined in CoreModule to register configurations when FeatureModule is initialized:

import { ErrorService } from '@core/error.service';

@NgModule({
    imports: [ CommonModule, ForFeatureModule, TranslateModule.forChild() ],
    declarations: [FeatureModule],
    providers: []
})
export class FeatureModule {
    constructor(
        private readonly translate: TranslateService, private readonly errorService: ErrorService) {
        translate.setTranslation('cz', i18n, true);

        // --- HERE --- errorService configures global error configuration
        errorService.addErrorMappings('FEATURE1', ERROR_MAPPING);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.