5

I have an Angular module lazy loaded called example.module. In example.module I have two different components called a.component and b.component and a bunch of different sub components both a and b use.

What I would like is that when the module is lazy loaded from the router I can route directly to either one of those two components based on which route the user selected from the parent routing.

The only work around I can think of is making two entirely separate modules each of which is lazy loaded independently with the common code being in a third shared module imported by the two. That seems like a lot more templated code and files I need to produce across my entire application rather then there being some way I can signal to a lazyloaded component to load one of the routes programmatically.

        RouterModule.forChild(
        [
          {
            path: "",
            redirectTo: "component-a" // How do I go to A or B?
          },
          {
            path: "component-a",
            component: ComponentA
          },
          {
            path: "component-b",
            component: ComponentB
          },
        ]

Thanks for your assistance and knowledge on the topic!

Edit - As requested root routing.

const appRoutes: Routes = [
  {
    path: "example",
    loadChildren: "./example.module#ExampleModule",
  },
];

@NgModule({
  imports: [
      RouterModule.forRoot(appRoutes)
  ],
  exports: [
      RouterModule
  ]
})
export class AppRoutingModule { }

Plunk - https://embed.plnkr.co/uiLFu0EBZ00F8sLH836w/

14
  • 1
    what is your forRoot config? Commented Sep 14, 2017 at 16:58
  • Added the main apps routing which contains forRoot which lazy loads the example module. Commented Sep 14, 2017 at 17:04
  • so when you navigate to /example your module is loaded and path:'' is applied, what do you want next? Commented Sep 14, 2017 at 17:06
  • Ideally I would like two routes called example-a and example-b. When the forRoot config navigates to example-a the lazy loaded module will load a specific path instead of always loading the default path. Commented Sep 14, 2017 at 17:09
  • 1
    it's working fine if you use routerLink="crisis-b/crisis-b". You seem to not understand the concepts behind routing Commented Sep 14, 2017 at 19:29

2 Answers 2

2

When working with lazy loaded modules you should treat them as eagerly loaded modules and the routes configuration you specify in the .forChild(routes) is merged into the single application wide configuration.

So in your particular case you define in the forRoot:

export const routes: Routes = [
  { path: 'crisis-a', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
  { path: 'crisis-b', loadChildren: 'app/crisis/crisis.module#CrisisModule' }
];

and in the .forChild()

const routes: Routes = [
  { path: 'crisis-a',    component: CrisisListComponentA },
  { path: 'crisis-b',    component: CrisisListComponentB },
];

So once merged you will have the following configuration:

export const routes: Routes = [
  { 
    path: 'crisis-a', 
    children: [
        { path: 'crisis-a',    component: CrisisListComponentA },
        { path: 'crisis-b',    component: CrisisListComponentB }
    ]
  { 
    path: 'crisis-b', 
    children: [
        { path: 'crisis-a',    component: CrisisListComponentA },
        { path: 'crisis-b',    component: CrisisListComponentB }
    ]
  }
];

Hence if you want to navigate to CrisisListComponentB with /crisis-b you have to specify full URL

/crisis-b/crisis-b
Sign up to request clarification or add additional context in comments.

2 Comments

just came across to the answer... Answer helped me also out! A small improvement though: routes: [ { path: 'crisis-a' : component: CrisisListComponentA} ] would still work and removes the duplication. So without the default paths in the child crisis router.
but it's not very user friendly to have all these double urls
1

I would make a canActivate guard to route them appropriately once the module is resolved.

Update the routes to be:

RouterModule.forChild(
[
  {
    path: "",
    canActivate: [RootRouteGuard]
  },
  {
    path: "component-a",
    component: ComponentA
  },
  {
    path: "component-b",
    component: ComponentB
  },
]

And then the guard would look something like this:

@Injectable()
export class RootRouteGuard implements CanActivate {

  constructor(private router: Router) {}

  public canActivate(route: ActivatedRouteSnapshot) {
    if (/* Logic */) {
      this.router.navigateByUrl('component-a');
    } else {
      this.router.navigateByUrl('component-b');
    }
  }
}

2 Comments

Looks like it would work. I'll test it out and accept as answer unless a better alternative comes up. Thanks!
This might be possible to do, when I tried it basically borks my app into an infinite loop because i'm calling navigateByUrl into the same module which then calls RootRouteGuard again. The actual answer was looking for was calling the route nested into the parent. I over complicated the problem. Thanks for your insight!

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.