Search code examples
angularangular-routingangular-module

Angular can't access child routes when using forChild


Hei, am currently working on an angular app, and facing an issue with loadChildren in the router. I posted a question earlier with a similar issue, but now is i hav ran all tests possible as well as moving the routing part of each module into separate modules. I can reach top level routes such as auth but not any of its children such as auth/login. My routing modules is s following:

app.router

export const routes: Routes = [
  {
    path: '',
    loadChildren: 'app/main/main.module#MainModule',
    canActivate: [OauthGuard]
  }, {
    path: 'auth',
    loadChildren: 'app/authentication/authentication.module#AuthenticationModule',
  }, {
   path: '**',
   component: PageNotFoundComponent,
   pathMatch: 'full'
   }
];

@NgModule({
  imports: [ RouterModule.forRoot(routes, {enableTracing: true}) ],
  exports: [ RouterModule ]
})
export class AppRouterModule {}

authentication.router

export const routes: Routes = [
  {
    path: '',
    component: AuthenticationComponent,
    children: [
      { path: '', redirectTo: 'login', pathMatch: 'full'},
      {
        path: 'register',
        component: RegisterComponent,
        outlet: 'auth'
      },
      {
        path: 'login',
        component: LoginComponent,
        outlet: 'auth'
      }
    ]}
];

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

When trying to navigate to auth/login i get the PageNotFoundComponent every time. I have enabled trace route and the path is not recognized, so i logged the routes registered getting following output:

Routes:  [
  {
    "path": "",
    "outlet": "app",
    "pathMatch": "full",
    "canActivate": [
      null
    ]
  },
  {
    "path": "auth",
    "loadChildren": "app/authentication/authentication.module#AuthenticationModule"
  },
  {
    "path": "**",
    "outlet": "app"
  }
]

So my routes never gets registered, even after carefully using forRoot and forChild on the different modules. I have read pretty much everything i can find on the topic, but in the the end pointing back to using the code i already have. I'm posting my ng version in case it's a bug or problem with this version.

My current setup

  • @angular/cli: 1.1.1
  • node: 6.10.3
  • os: win32 x64
  • @angular/animations: 4.1.3
  • @angular/common: 4.1.3
  • @angular/compiler: 4.1.3
  • @angular/core: 4.1.3
  • @angular/forms: 4.1.3
  • @angular/http: 4.1.3
  • @angular/material: 2.0.0-beta.6
  • @angular/platform-browser: 4.1.3
  • @angular/platform-browser-dynamic: 4.1.3
  • @angular/platform-server: 4.1.3
  • @angular/router: 4.1.3
  • @angular/cli: 1.1.1
  • @angular/compiler-cli: 4.1.3
  • @ngtools/json-schema: 1.1.0
  • @ngtools/webpack: 1.4.1

Anyone had a similar problem, or knows how to solve this ?


Solution

  • By defining:

    export const routes: Routes = [
      {
        path: '',
        component: AuthenticationComponent,
        children: [
          { path: '', redirectTo: 'login', pathMatch: 'full'},
          {
            path: 'register',
            component: RegisterComponent,
            outlet: 'auth'
          },
          {
            path: 'auth/login',
            component: LoginComponent,
            outlet: 'auth'
          }
        ]}
    ];
    
    @NgModule({
      imports: [ RouterModule.forChild(routes) ],
      exports: [ RouterModule ]
    })
    export class AuthenticationRouterModule {}
    

    To render the LoginComponent, you would have to navigate to root/auth/auth/login. As soon as you enter the path auth in the routes used in the forRoot method, the path used to load the children will be added to them as prefix.

    To achieve what you want, you need to define the following routes:

    export const routes: Routes = [
      {
        path: '',
        component: AuthenticationComponent,
        children: [
          { path: '', redirectTo: 'login', pathMatch: 'full'},
          {
            path: 'register',
            component: RegisterComponent,
            outlet: 'auth'
          },
          {
            path: 'login',
            component: LoginComponent,
            outlet: 'auth'
          }
        ]}
    ];
    
    @NgModule({
      imports: [ RouterModule.forChild(routes) ],
      exports: [ RouterModule ]
    })
    export class AuthenticationRouterModule {}
    

    EDIT:

    After taking a look at the documentation for named outlets, to navigate to LoginComponent you need the following path:

    root/auth(auth:login)
    

    This is because the component will be rendered by a named outlet. For further info take a closer look to the docs.