I have an app module that is doing:
export const MY_TOKEN = new InjectionToken<any>('MY_TOKEN');
@NgModule({
imports: [
ApiModule,
AppRoutingModule,
],
providers: [
{ provide: MY_TOKEN, useValue: 'hello' },
],
...
that app routing module has a route:
{
path: '',
loadChildren: () => import('./open.module').then(m => m.OpenModule),
},
That open module is doing:
@NgModule({
imports: [
OpenRoutingModule,
],
providers: [
{ provide: MY_TOKEN, useValue: 'lol' },
],
and then the open routing module has a path that that lazy loads a module / component
{
path: 'some/where',
loadChildren: () => import('./something.module').then(m => m.SomethingModule),
},
...
Ok, so next, I have an HTTP interceptor that is provided in the ApiModule
...
@NgModule({
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true },
],
})
export class ApiModule {}
and in that intercepter, I am doing:
constructor(
@Inject(MY_TOKEN) public val: any
) {
console.log(val);
}
When the component in the open module makes api calls, the value is hello
rather than lol
...
I thought at first this might be because the interceptor is getting instantiated before the module that gives the provider for the token, so then I tried using the injector directly in the interceptor:
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
console.log(this.injector.get(MY_TOKEN));
...
But that still logs hello
instead of lol
... Why is the provider I specified in the Open module not getting used?
The only way I could figure out how to do this was to initially have an object set and mutate that object in the various modules...
export interface Context {
open?: boolean;
}
export const context: Context = {};
export const CONTEXT = new InjectionToken<Context>('CONTEXT', {
providedIn: 'root',
factory: () => context,
});
// app module:
{ provide: CONTEXT_TOKEN, useValue: context },
// open module
export class OpenModule {
constructor(@Inject(CONTEXT) context: context) {
context.open = true;
}
}
// other modules
export class ModuleXYZ {
constructor(@Inject(CONTEXT) context: context) {
context.open = false;
}
}
Now the interceptor has the correct state....... I really just wanted to be able to not have this http interceptor be applied to things in the Open module, but that apparently was not possible because when I initially tried providing the http interceptors in the further down modules then they were never being applied... So I have had to resort to this dumb "context" code so that the interceptor can do:
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
if (this.context.open) {
return next.handle(request);
}
...
If anyone has any suggestions on how I can do this in a less dumb way, I'd greatly appreciate it..