Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement routed tabs with angular material, within a child route?

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?

like image 213
S. Caruso Avatar asked Sep 13 '19 10:09

S. Caruso


People also ask

How does Angular routing handle route parameters?

To access the route parameters, we use route.snapshot , which is the ActivatedRouteSnapshot that contains information about the active route at that particular moment in time. The URL that matches the route provides the productId . Angular uses the productId to display the details for each unique product.

What is nested routing in Angular?

Nested routes are routes within other routes. In this tutorial, we will show you how to create a child route and display the child components. The Angular allows us to nest child routes under another child routes effectively creating a Tree of routes.

What is Children in routing Angular?

With child routes, you can have a component-like structure defined for the routes in your app. It is critical as there are views that the user should not be able to access unless they are in a particular view. This way, the structure becomes tree-like, just like the structure of components.


2 Answers

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

like image 75
janders Avatar answered Nov 03 '22 11:11

janders


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>
like image 40
Alverson Layne Avatar answered Nov 03 '22 09:11

Alverson Layne