Home > Enterprise >  How to properly declare a child route for the angular router?
How to properly declare a child route for the angular router?

Time:05-17

I've the following routing:

//Root routes
const routes: Routes = [
  {
    path: '',
    component: AuthenticatedLayoutComponent, //All childs pages will have headers
    children: [
      { path: '', redirectTo: 'documents', pathMatch: 'full' },
      { path: 'documents', loadChildren: () => import('./documents/documents.module').then(m => m.DocumentsModule) },
      { path: 'settings', loadChildren: () => import('./settings/settings.module').then(m => m.SettingsModule) },
      { path: 'accounts', loadChildren: () => import('./account/account.module').then(m => m.AccountModule) },
    ],
    canActivate: [AuthGuard],
  },
  {
    //The goal of separating auth and account is to have the pages to becomes authentified in the Auth module, with a totally different layout
    path: 'auth',
    loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule),
    canActivate: [UnauthGuard],
  },
];

and then, for the child "AccountModule", I've the following routes:

const routes: Routes = [
  { path: 'profile', component: ProfileComponent },
  { path: '', redirectTo: 'profile', pathMatch: 'full' },
];

My AuthenticatedLayoutComponent has basically just a header/footer and a router-outlet:

<div id="container" >
  <header >
    <app-header></app-header>
  </header>
  <main >
    <router-outlet></router-outlet>
  </main>
  <footer >
    <app-footer></app-footer>
  </footer>
</div>
  • If I try to access to http://localhost:4200/accounts/profile everything works
  • But a strange thing is that if I'm trying to access to http://localhost:4200/profile I'm also redirected to my ProfileComponent, without my header/footer.

Why is this considered a valid path and how do I prevent it?

CodePudding user response:

Like figured out in the comments, the problem is that the application root module imports AccountModule because it contains something that the application root module needs. In that moment, the route definition of the AccountModule is loaded, which exposes the /profile route.

One way to fix it, is to resolve the dependency between the root module and the AccountModule, and stop importing it. Then the module with its route definition is only loaded via lazy loading, making the /profile route unavailable. But possibly this will be a lot of effort.

Another quicker way to fix it, is to remove lazy loading from the /accounts route and define its sub-routes directly in your root routing module:

//Root routes
const routes: Routes = [
  {
    path: '',
    component: AuthenticatedLayoutComponent, //All childs pages will have headers
    children: [
      // ...
      {
        path: 'accounts',
        children: [
          { path: 'profile', component: ProfileComponent },
          { path: '', redirectTo: 'profile', pathMatch: 'full' },
        ]
      },
    ],
    canActivate: [AuthGuard],
  },
  // ...
];

CodePudding user response:

Strongly inspired by @JSONDerulo answer:

Since I cannot use lazy loading but I still would like to have my rules enclosed in my accounts module:

  1. I now declare the module in my AppModule
  2. I export my account routes and use them as childs in my AppRoutingModule
  3. I removed the import of the AccountRoutingModule of my AccountModule

AppRoutingModule:

import { routes as accountsRoutes } from './account/account-routing.module';
const routes: Routes = [
  {
    path: '',
    component: AuthenticatedLayoutComponent, //All childs pages will have headers
    children: [
      { path: '', redirectTo: 'documents', pathMatch: 'full' },
      { path: 'documents', loadChildren: () => import('./documents/documents.module').then(m => m.DocumentsModule) },
      { path: 'settings', loadChildren: () => import('./settings/settings.module').then(m => m.SettingsModule) },
      { path: 'accounts', children: accountsRoutes },
    ],
    canActivate: [AuthGuard],
  },
  {
    //The goal of separating auth and account is to have the pages to becomes authentified in the Auth module, with a totally different layout
    path: 'auth',
    loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule),
    canActivate: [UnauthGuard],
  },
];

AccountRoutingModule

export const routes: Routes = [
  { path: 'profile', component: ProfileComponent },
  { path: '', redirectTo: 'profile', pathMatch: 'full' },
];
  • Related