Reputation: 207
I want to use Angular Material tabs https://material.angular.io/components/tabs with a router navigation in the tabs.
I tried to use <nav mat-tab-nav-bar>
as indicated in the doc, and I found this tutorial: https://nirajsonawane.github.io/2018/10/27/Angular-Material-Tabs-with-Router/
where I can find a template like that:
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.link"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
</a>
</nav>
<router-outlet></router-outlet>
But the problem is, that my tabs are not at the root of my application, but are in a submodule in a child route. I have something like that:
In app-routing-module:
const routes: Routes = [
...
{ path: 'subpath', loadChildren: () => import('./path-to-module/submodule.module').then(m => m.SubmoduleModule) },
...
];
In submodule-routing-module I should have something like that:
const routes: Routes = [
{ path: '', component: FirstTabComponent },
{ path: 'tab2', component: SecondTabComponent },
]
What I would like is that, if I go to url /subpath
I see the tabs with the first tab selected, and if I go to url /subpath/tab2
I see the tabs with the second tab selected.
Any idea how to do that?
Upvotes: 10
Views: 44934
Reputation: 1
the same code previously see, but updated
************* code updated ******** (12-05-2022, version angular recent)
<nav mat-tab-nav-bar >
<a mat-tab-link *ngFor="let link of navLinks"
(click)="activeLink = link.link"
[routerLink]="link.link"
[active]="activeLink == link.link"> {{link.label}} </a>
</nav>
<router-outlet></router-outlet>
Upvotes: 0
Reputation: 976
An alternative to janders solution is to use the router dependency. With router.url()
function, you are able to compare the current active url with your navigation links.
In your Component.ts
:
...
rootUrl = '/path/to/your/component';
navigation = [
{
name: 'Table',
link: '',
},
{
name: 'Stats',
link: '/stats',
},
{
name: 'Settings',
link: '/settings',
},
{
name: 'Export',
link: '/export',
}
];
constructor(private route: ActivatedRoute, public router: Router) {
...
}
...
In your Component.html
:
...
<nav mat-tab-nav-bar mat-align-tabs="left">
<a mat-tab-link
*ngFor="let l of navigation"
[routerLink]="rootUrl + l.link"
[active]="this.router.url === rootUrl + l.link">
{{l.name}}
</a>
</nav>
...
In your router:
...
{
path: '/path/to/your/component',
component: Component,
canActivate: [AuthGuard],
children: [
{
path:'',
pathMatch: 'full',
component: TableComponent
},
{
path:'settings',
pathMatch: 'full',
component: SettingsComponent
},
{
path:'export',
pathMatch: 'full',
component: ExportComponent
},
{
path:'stats',
pathMatch: 'full',
component: StatsComponent
}
]
}
...
Upvotes: 4
Reputation: 141
I, too, ran into the same issue. I cloned Angular-Material-Tabs-with-Router but modified it with a child component that also has child components.
The child component is called home
and in home.component.html
it implements:
<nav mat-tab-nav-bar>
<a mat-tab-link
*ngFor="let link of navLinks"
[routerLink]="link.link"
routerLinkActive #rla="routerLinkActive"
[active]="rla.isActive">
{{link.label}}
</a>
</nav>
<router-outlet></router-outlet>
This creates 3 tabs called Notes
, Photos
and Documents
. The Notes
tab includes additional components to list, view, edit and delete notes.
I created and added the source to GitHub and imported it to Stackblitz:
Upvotes: 14
Reputation: 117
I had the same issue. The problem came from the routing module.
In order to inherit the imported Material classes, the path for children must be lazy-loaded instead of being directed from the component.
This caused the problem:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: 'customers',
// Don't use this method in order to link to children!
component: 'CustomerListComponent'
}
The 'customer list' template loaded, but without formatting. Also, Angular threw an error because it could not find the 'mat-tab' directive anywhere, even though it was being imported in the parent component, orders.module.ts
.
This was the solution: src > app > app-routing.module.ts
const routes: Routes = [{
path: 'customers',
loadChildren: () =>
import ('./customers/customers.module').then(m => m.CustomersModule)
}
Here are the related files from the project:
src > app > orders > orders.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OrdersRoutingModule } from './orders-routing.module';
import { OrderListComponent } from './order-list/order-list.component';
// Material components
import { MatTabsModule } from '@angular/material/tabs';
@NgModule({
imports: [
CommonModule,
OrdersRoutingModule,
MatTabsModule
],
declarations: [
OrderListComponent
]
})
export class OrdersModule { }
src > app > orders > orders-list > orders-list.component.html
<mat-tab-group>
<mat-tab label="Orders">
<ng-template matTabContent>
<p>Orders here.</p>
</ng-template>
</mat-tab>
<mat-tab label="Shipments">
<ng-template matTabContent>
<p>Shipments here.</p>
</ng-template>
</mat-tab>
<mat-tab label="Archived">
<ng-template matTabContent>
<p>Really old orders here.</p>
</ng-template>
</mat-tab>
</mat-tab-group>
Upvotes: 3
Reputation: 648
If my understanding is right, you want to navigate to a component in a lazy loaded module.
For this I made a stackblitz, which might be useful for you.
Here's the basic code for your understanding
<nav mat-tab-nav-bar class="mat-elevation-z8" >
<a
mat-tab-link
*ngFor="let link of navLinks"
routerLink="{{ link.location }}"
routerLinkActive
#rla="routerLinkActive"
[active]="rla.isActive"
>
<mat-icon>{{ link.icon }}</mat-icon>
<span>{{ link.label | uppercase }}</span>
</a>
</nav>
in ts
navLinks = [
{location:'',label:'dummy',icon:'menu'},
{ location: '/shared', label: 'Overview', icon: 'account_circle' },
{ location: '/shared/sub', label: 'Experience', icon: 'work' }
];
Upvotes: 3