问题
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?
回答1:
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>
    回答2:
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:
GitHub
Stackblitz
回答3:
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' }
  ];
Stackblitz
回答4:
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
      }
    ]
  }
...
    来源:https://stackoverflow.com/questions/57921846/how-to-implement-routed-tabs-with-angular-material-within-a-child-route