3
votes

I'm creating a dashboard app and so far I have two lazy loaded modules AuthModule and AdminModule My app-routing-module.ts looks like this

const routes: Routes = [
    {
     path: '',
     loadChildren: './auth/auth.module#AuthModule'
    },
    {
     path: 'admin',
     loadChildren: './admin/admin.module#AdminModule',
     canActivate: [AuthGuardService]
    },
    {
      path: '**',
      component: NotFoundComponent
    }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

My app.component.html has a <router-outlet></router-outlet> that should render the above routes inside it.

so these urls are working /auth/ and /admin/ perfectly

In my admin-routing.module.ts I have the following routes

const routes: Routes = [
  {
    path: '',
    component: AdminComponent,
    children: [
      {path: '', pathMatch: 'full', redirectTo: 'dashboard'},
      {path: 'dashboard', component: DashboardComponent },
      {path: 'users', component: UsersComponent },
      {path: 'reports', component: ReportsComponent },
      {path: 'booking', component: BookingComponent }
    ]
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})

so that /admin/ route directly navigates to /admin/dashboard/ which is also working perfectly.

In my admin.component.html I added another <router-outlet></router-outlet> that should renders AdminModule routes inside it, so I can have a sidenav bar layout.

The problem is that only the default route for AdminModule which is /admin/dashboard renders perfectly inside the second router-outlet whenever I try to navigate to any other child route like /admin/users/ or /admin/booking/ the app redirects to NotFoundComponent

Here's my problem illustrated. default child route for the admin module 'dashboard' trying to hit another child route

3

3 Answers

1
votes

I finally figured out the solution.

In your app.module file change the code to look like this:

   const routes: Routes = [
        {
         path: '',
         component: AuthComponent, //<--- Add this
         loadChildren: './auth/auth.module#AuthModule'
        },
        {
         path: 'admin',
         component: AdminComponent, //<--- Add this
         loadChildren: './admin/admin.module#AdminModule',
         canActivate: [AuthGuardService]
        },
        {
          path: '**',
          component: NotFoundComponent
        }
    ];

    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    }

)

In your lazy-loaded module routing file (admin-routing.module.ts) change the code to look like this:

const routes: Routes = [

      {path: '', pathMatch: 'full', redirectTo: 'dashboard'},
      {path: 'dashboard', component: DashboardComponent },
      {path: 'users', component: UsersComponent },
      {path: 'reports', component: ReportsComponent },
      {path: 'booking', component: BookingComponent }

];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})

Now your code should work as expected

0
votes

try this

{
  path: '',
  component: AdminComponent,
  children: [
    {path: '', pathMatch: 'full', redirectTo: 'dashboard'},
    {
      path: 'dashboard', 
      component: DashboardComponent,
      children: [
        {path: 'users', component: UsersComponent },
        {path: 'reports', component: ReportsComponent },
        {path: 'booking', component: BookingComponent }
      ]
    }
  ]
}
0
votes

The way you define admin-routing.module.ts means that all child routes expect an element inside the AdminComponent's template. Angular will try to render all children into the AdminComponent.

I had the same problem. I didn't manage to render the child routes of a lazy loaded module inside the root router-outlet. I solved this issue by the following algorithm:

For each child Component c of a lazy loaded module M that should be rendered in the AppComponent's outlet:

  • create a lazy loaded module for c
  • define a route in your app-routing.module under root with the path needed that points to the lazy loaded module c
  • remove the route from M's routing declaration

For admin/users this could look something like this:

app-routing-module.ts

const routes: Routes = [
    {
     path: '',
     loadChildren: './auth/auth.module#AuthModule'
    },
    {
     path: 'admin',
     loadChildren: './admin/admin.module#AdminModule',
     canActivate: [AuthGuardService]
    },
    {
     path: 'admin/users',
     loadChildren: './admin/users/admin-users.module#AdminUsersModule',
     canActivate: [AuthGuardService]
    },
    {
      path: '**',
      component: NotFoundComponent
    }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

This solution has a couple of drawbacks:

  1. you cannot encapsulate your modules as expected, i.e. the parent-child semantics gets lost
  2. you cannot simply reuse deserialized modules from parent routes - in case you have deep nesting

So it's not ideal, but it works.