angulartypescriptangular18angular-di

How to provide an angular guard in a specific injection context?


I have a monorepo that contains several applications as well as some shared libraries. What I am trying to do is implement an authGuard for some of the pages in the applications, however the issue I am running into is that, in the context of the router, my AuthService has no provider.

This is because the dependencies of AuthService look like this:

AuthService -> FirebaseAuthService -> FirebaseAppService -> EnvironmentService

On top of that, I am trying to prevent services and modules being initialized unnecessarily. So, AuthService should only be initialized if I try to navigate to a page that requires authentication, or I am on the authentication page (ideally, I would have some informational pages that don't require auth).

Attempting to wrap my guard in runInInjectionContext seems to make things worse because not only can I not use an NgModule type as a value for the Injector parameter, but writing the function for the second parameter in a way that satisfies the CanMatchFn specs makes it so that there are even more errors.

I really can't provide AuthService in 'root' because of the initialization process for the app's environment.


Solution

  • I came to realize that I was looking at my injectors wrong. What I ended up doing is the following:

    /*environment.model.ts*/
    export interface IEnvironmentModel {
        // ...
    }
    
    export const ENVIRONMENT_INJECTION_TOKEN = new InjectionToken<IEnvironmentModel>('environment-model');
    
    /*app.module.ts*/
    @NgModule({
        // ...
        providers: [
            {
                provide: ENVIRONMENT_INJECTION_TOKEN,
                useValue: environment
            }
        ]
    })
    export class AppModule {}
    

    This way, I could do @Injectable({ providedIn: 'root' }) for AuthService as well as all of it's dependencies.

    When I tested this, I found that if ENVIRONMENT_INJECTION_TOKEN was not provided in the app module, I would get a null injector error, but as long as it was provided, I could use all of the services that I needed.