bluebit
bluebit

Reputation: 83

How do I navigate different child components within a mat-tab? (not in primary outlet)

My AppComponent contains a sidenav and a router-outlet. Each menu item allows me to navigate to a different feature. Each feature module has four main components:

When I click a feature from the sidenav I'm presented with the features' list-component by default.

On each features' list-component I'm using navigation buttons to navigate to the corresponding details, edit and add components via URL like this: this.router.navigateByUrl('/feature/details/123').

One of my features has a mat-tab-group in its 'details component'. When I navigate to this component (e.g. /feature/details/123) I would also like to be able to click on some tab and see a list-component. But to be clear, I want this component visible within the tab, not in the primary outlet. This list should show a table with some data from id:123. Also this embeded list-component should have different buttons to allow me to navigate to its corresponding details, edit and add components.

I've tried to implement auxiliary routes, and named router-outlets, but I must be doing something wrong because I just can't get this to work. I may not understand the innerworkings properly.

Could someone please explain how I should tackle this? If it is even possible at all?

Upvotes: 3

Views: 3271

Answers (1)

Sven
Sven

Reputation: 97

You could map a DetailsComponent to the /feature/details route and use the :id route as a child of the details route. In the DetailsComponent you would use the material tabs with routing

in routing module

const routes: Routes = [
  {
    path: 'feature',
    children: [
      {
        path: 'list',
        component: ListComponent
      },
      {
        path: 'details',
        component: DetailsComponent,
        children: [
          {
            path: ':id',
            component: TabIdComponent,
            data:
            {
              title: 'Detail',
            }
          },
          {
            path: 'list',
            component: ListComponent,
            data:
            {
              title: 'List',
            }
          },
          ...
          {
            path: '',
            redirectTo: 'list',
            pathMatch: 'full'
          },
        ]
      },
      ...
    ]
  }

];

in details.component.html

<nav mat-tab-nav-bar>
   <a mat-tab-link
            *ngFor="let tab of tabs"
            [routerLink]="tab.link"
            routerLinkActive
            #rla="routerLinkActive"
            [active]="rla.isActive"
          >
            {{ tab.label }}
   </a>
</nav>
<router-outlet></router-outlet>`

To get the list of tabs from the router config you list it from the ActivatedRoute in the details.component.ts

public tabs: Tab[];

constructor(activatedRoute: ActivatedRoute) {

    activatedRoute.paramMap.subscribe(value => {
      this.tabs = new List(activatedRoute.snapshot.routeConfig.children)
          .Where(r => r.path !== '')
          .Select(r => new Tab(r.path, r.data.title)).ToArray();
    });
  }


...

export class Tab {
    link: string;
    label: string;

    constructor(link: string, label: string) {
        this.label = label;
        this.link = link;
    }
}


If you don't want the ListComponent to ever load in the primary outlet (not even when navigating to /feature/list) you can redirect it to /feature/details/list instead it of defining a component for that route using

{
  path: 'list',
  redirectTo: 'details/list',
  pathMatch: 'full'
}

Upvotes: 2

Related Questions