Conditionally load module on the empty path in Angular router

It turns out that this was basically not (safely) possible until Ivy. Now in Angular 9/10 we can lazy load feature-modules without the router very easily.

StackBlitz
V13 StackBlitz Update

@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
})
export class AppComponent implements OnInit  {
    @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;

    constructor( 
        private compiler: Compiler,
        private injector: Injector
    ){  }

    public ngOnInit(): void {
        if (loggedin) {
            this.loadModule(await import('./lazy/lazy.module').then(m => m.LazyModule));
        } else {
            this.loadModule(await import('./lazy2/lazy2.module').then(m => m.Lazy2Module));
        }
    }

    async loadModule(module: Type<any>) {
        let ref;
        try {
            this.container.clear();

            // Angular < 13 
            const moduleFactory = await this.compiler.compileModuleAsync(module);
            const moduleRef: any = moduleFactory.create(this.injector);
            const componentFactory = moduleRef.instance.resolveComponent(); // ASSERTION ERROR
            ref = this.container.createComponent(componentFactory, null, moduleRef.injector);

            // Angular 13 update
            const moduleRef = createNgModuleRef(module, this.injector);
            const componentFactory = moduleRef.instance.resolveComponent();
            ref = container.createComponent(
                componentFactory,
                undefined,
                moduleRef.injector
            );

        } catch (e) {
            console.error(e);
        }
            return ref;
        }
    }

There are a couple things that you are doing wrong in my opinion.

  1. You shouldn't have two routes defined with the same path.
  2. In your guard the map is pointless. As long as your service method returns Observable<boolean> you don't need to map its value.
  3. Also in your guard if you're not returning true, you need to navigate to the other module's path. For that you will need to implement some other logic for telling whether the user is logged in or not.

Take a look at the official angular routing guide here. There is a lot of useful information that will help you. Especially these:

  • recommended guard implementation
  • debugging routing in your application

EDIT 2018/12/27

So if the question is how to conditionally load two feature modules on the same path,

the answer is, in my experience, you cannot.