Reputation: 271
We have a basic application with 2 tabs, each with its own named outlet
<mat-tab-group>
<mat-tab label="Tab1">
<router-outlet name="tab1"></router-outlet>
</mat-tab>
<mat-tab label="Tab2">
<router-outlet name="tab2"></router-outlet>
</mat-tab>
</mat-tab-group>
One of the 2 named outlets just renders a component and that's fine. For the second one, we want to be able to route between different views so we created its own module and lazy load it.
App routing looks like
const routes: Routes = [{
path: '',
children: [{
path: '',
redirectTo: '/home',
pathMatch: 'full'
}, {
path: 'login',
loadChildren: () => import('./login/login.module').then(m => m.LoginModule)
},
{
path: 'home',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
}]
}]
Home page's routing looks like
const routes: Routes = [{
path: '',
component: HomeComponent,
children: [{
path: '',
component: Tab1Component,
outlet: 'tab1'
}, {
path: '',
outlet: 'tab2',
loadChildren: () => import('./tab2/tab2.module').then(m => m.Tab2Module)
}]
}];
Tab2Module is implemented as follows
const routes: Routes = [{
path: '',
component: Tab2Child1Component
}, {
path: 'tab2-child',
outlet: 'tab2',
component: Tab2Child2Component
}]
Tab2Child1Component gets rendered fine but we cannot navigate to Tab2Child2Component.
I am trying the following:
this.router.navigate([{ outlets: { tab2: 'tab2-child' } }], { relativeTo: this.route });
I can see in tracing that router is indeed trying to route to /home/(tab2:tab2-child)
but in the end it just redirects back to /home
with an error:
Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'home'
Error: Cannot match any routes. URL Segment: 'home'
Stackblitz showcasing the error: https://stackblitz.com/edit/angular-ivy-pv5jsi
Upvotes: 1
Views: 1887
Reputation: 12082
You have two issues with your design that cause it not to work.
loadChildren
for tab2 is like the component inside tab2 will have more internal routes which is not true in your case since you do not have another router outlet in the Tab2Child1Component
.To change your sample to something that works you need to add a path to the HomeComponent
inside the HomeModule
. To lazy load the tabs you need to put all the tabs in one module that is loaded as the children of the home component.
Here is my implementation of the HomeModule
with the changes needed.
const routes: Routes = [
{
path: '',
redirectTo: 'hc',
pathMatch: 'full'
},
{
path: 'hc',
component: HomeComponent,
loadChildren: () => import("./tab.module").then(m => m.TabModule)
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
declarations: [HomeComponent]
})
export class HomeModule {}
And the implementation of the tab module that defines the tabs for both outlets.
const routes: Routes = [
{
path: '',
component: Tab1Component,
outlet: "tab1"
},
{
path: '',
outlet: 'tab2',
component: Tab2Child1Component
},
{
path: 'tab2-child',
outlet: 'tab2',
component: Tab2Child2Component
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
declarations: [Tab2Child1Component, Tab2Child2Component]
})
export class TabModule {}
In the app module redirect directly to the sub path for some reason the redirect in the module does not work if you redirect just to home.
{
path: "",
redirectTo: "/home/hc",
pathMatch: "full"
},
Here is a link to a fork of your StackBlitz with the full implementation.
If it is a requirement for you to have separate lazy load modules for each tab then you need to create separate components for each tab that have one router outlet inside to display the tab child components so you get a two level navigation structure. Since I don't know what is your exact use case I cannot say if this would be a better solution.
Upvotes: 2