I have a difficult time understanding the exact algorithm angular router uses, specifically for auxiliary routes.
What I've done
I've read docs where didn't find any clue about how the route matching works, especially for auxiliary routes (maybe I just didn't find, but I tried very hard), but found question that explained the process for regular routes.
I've googled and solved a few related problems. More specifically, I had a problem with a parent who has blank path
, which doesn't allow some auxiliary routes work properly, see this and that
Example
The example is derived from my project. Suppose I have two main modules in my app (and 2 routing modules, 4 in total).
app.module.ts
...
@NgModule({
declarations: [
AppComponent,
NotFoundComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
AdminModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.component.ts
...
const routes: Routes = [
{path: '**', component: NotFoundComponent}
];
@NgModule({
imports: [AdminModule, RouterModule.forRoot(routes, {enableTracing: true})],
exports: [RouterModule]
})
export class AppRoutingModule {
}
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>\n',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'Results System';
}
admin-routing.module.ts
...
const routes: Routes = [
{
path: 'dashboard', component: DashboardComponent, children: [
{ path: 'competitions', component: CompetitionsListComponent},
{ path: '', component: DashboardNavComponent, outlet: 'sidebar'},
{ path: 'create', component: CreateComponent, outlet: 'details'},
]
},
{ path: '', pathMatch: 'full', redirectTo: 'dashboard'}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AdminRoutingModule {
}
admin.module.ts - excluded, nothing special, just import admin-routing.module.ts module
dashboard.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-dashboard',
template: `
<router-outlet name="sidebar"></router-outlet>
<router-outlet name=""></router-outlet>
<router-outlet name="details"></router-outlet>
`,
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
Results
localhost:4200/dashboard/competitions
two children components (CompetitionsListComponent
,DashboardNavComponent
) are rendered as expectedlocalhost:4200/dashboard/competitions(details:create)
link won't render all three children components (CompetitionsListComponent
,DashboardNavComponent
,CreateComponent
) and just throw an error:
NavigationError(id: 1, url: '/dashboard/competitions(details:create)', error: Error: Cannot match any routes. URL Segment: 'create')
localhost:4200/dashboard/competitions(details:create)
same
NavigationError(id: 1, url: '/dashboard/competitions(details:dashboard/create)', error: Error: Cannot match any routes. URL Segment: 'dashboard/create'
What I don't understand
- How exactly a child module adds its routing configs to the root configs? Does lazy loading affects this in any way? Is it just appended to the object like that?:
[
// children module routes
{
path: 'dashboard', component: DashboardComponent, children: [
{ path: 'competitions', component: CompetitionsListComponent},
{ path: '', component: DashboardNavComponent, outlet: 'sidebar'},
{ path: 'create', component: CreateComponent, outlet: 'details'},
]
},
{ path: '', pathMatch: 'full', redirectTo: 'dashboard'}
...other children module routes...
// root module routes
{path: '**', component: NotFoundComponent},
];
- Why
NotFoundComponent
doesn't work in the case (when error appears), doesn't it cover every path, or auxiliary routes have to have this pattern for every outlet like that:
{path: '**', component: NotFoundComponent, outlet: 'sidebar'}
{path: '**', component: NotFoundComponent, outlet: 'details'}
How does an auxiliary route find a named outlet it'll use? Does it search for the first parent with the appropriate outlet and if don't find, throws an error (excluding a case from the point above)?
And in the end why
localhost:4200/dashboard/competitions(details:create)
isn't resolved toDashboardComponent
withCreateComponent
inside. Do I need to specify url for auxiliary route another way? More specifically, how are auxiliary paths resolved in the context when they are children of other non-auxiliary route components?