How to make a named routing outlet work with loadC

2019-03-14 18:25发布

I've created two plunkers concerning an issue with routing's loadChildren and outlet navigation. For some reason, having an empty base path within the loaded child module does not work with outlet navigation.

In this example, pressing the 'Contact' link fails.

app-routing.module

const appRoutes: Routes = [
  { path: 'admin', loadChildren: () => AdminModule },
  { path: '',   redirectTo: '/admin', pathMatch: 'full' }
];

admin-routing.module

const adminRoutes: Routes = [
{ 
  path: '', 
  component: AdminComponent,
  children: [ 
    {
      path: 'compose',
      component: ComposeMessageComponent,
      outlet: 'popup'
    }
  ]
}];

In this example, pressing the 'Contact' link works.

app-routing.module

const appRoutes: Routes = [
  { path: 'admi', loadChildren: () => AdminModule },
  { path: '',   redirectTo: '/admi/n', pathMatch: 'full' }
];

admin-routing.module

const adminRoutes: Routes = [
{ 
  path: 'n', 
  component: AdminComponent,
  children: [ 
    {
      path: 'compose',
      component: ComposeMessageComponent,
      outlet: 'popup'
    }
  ]
}];

The difference is in the app-routing.module and the admin-routing.module. The working example doesn't have an empty path for the admin-routing.module. According to the documentation having an empty path should work.

1条回答
劳资没心,怎么记你
2楼-- · 2019-03-14 18:34

The first segment of the link parameters array of your the routerLink directive for "Contact" refers to the parent route and corresponding router-outlet for the component template containing the routerLink. You would need to place the route config for the named router-outlet in the app-routing config instead of the admin-routing config for the 'fails' scenario, but this is likely undesirable due to separation of concerns amongst other principles.

The difference between the first example you provided that 'fails' and the second example that 'works' lies in the way in which the angular router redirectTo in the route config "backtracks" during pattern matching of routes; however, the second key aspect is the behavior that is evaluated as a result of matching should not affect the behavior of pattern matching of the route.

In the 'fails' scenario, the route segment '' is matched, redirectTo changes the url to '/admin', the router matches the path '/admin', the router automatically matches empty string '' in the admin-routing config, routing is complete. In the second 'success' scenario, the path is matched '', redirectTo matches the first segment '/admi', the router evaluates the second segment of the url '/n' as routing is not complete yet, the router looks in the app-routing config for matches '/n' and doesn't find any matches, the admin-routing config is then evaluated and the second segment '/n' is matched, the router automatically matches empty string '' routing is complete. The 'fails' scenario issue is that the link parameters array of the <a [routerLink]="[{ outlets: {popup: ['compose']}}]">Contact</a> is an empty string and the url is currently '/admin'. Yes, the key difference is location in the hierarchy at which the empty '' string automatically evaluated by the router occurs, in other words, the location at which the router evaluation of the routes configuration completes. It is subtle but the empty string evaluated in the 'fails' scenario completes at the top level AdminComponent; therefore, router pattern matching backtracking looks for empty string '' automatically at the parent route 'admin', as result of the redirectTo in the app-routing routes config. In the second 'success' scenario, the router evaluation of the routes config completes at the child path '' of the parent '/n' which is level below in the hierarchy compared to the admin-routing routes config 'fails' scenario; therefore, in the second 'success' scenario, the '' empty string that is automatically evaluated is unaffected by the redirect from the app-routing routes config when the <a [routerLink]="['', { outlets: {popup: ['compose']}}]">Contact</a> is clicked.

In order to fix the 'fails' scenario routing config you need to modify either the first segment of the links parameter array of your Contact routerLink directive to specify the admin path i.e., <a [routerLink]="['/admin', { outlets: {popup: ['compose']}}]">Contact</a>, or modify the hierarchy at which the empty string '' path that is automatically evaluated by the router completion occurs.

To "fix" by modifying the routes config hierarchy at which the empty string '' path that is automatically evaluated by the router the parent, it is important to note that the parent of the empty string '' path must not be an empty string '' path. In example:

const devNavRoutes: Routes = [
  {
    path: '',
    component: DevNavContainerComponent, canActivate: [ DevNavAuthGuard1Service ],
    children: [
      { path: '', canActivateChild: [ DevNavAuthGuard1Service ],
        children: [
          { path: '', redirectTo: 'dashboard' },
          { path: 'dashboard', component: DevNavDashboardComponent,
            children: [
              { path: ':auxiliaryId', component: DevNavAuxiliaryComponent, outlet: 'auxiliary'},
              { path: ':ancillaryId', component: DevNavAncillaryComponent, outlet: 'ancillary' }
            ] },
          { path: ':id', component: DevNavDashboardComponent,
            children: [
              { path: ':auxiliaryId', component: DevNavAuxiliaryComponent, outlet: 'auxiliary'},
              { path: ':ancillaryId', component: DevNavAncillaryComponent, outlet: 'ancillary' }
            ] },
        ] },
    ] } 
];

Note:

// dev-nav-container.component
<router-outlet></router-outlet>

And

// dev-nav-dashboard.component
<router-outlet name="auxiliary"></router-outlet> 
<router-outlet name="ancillary"></router-outlet>
查看更多
登录 后发表回答