angulartypescriptangular-materialtabsmat-tab

Angular - Set a mat-tab-link active after a tab is closed


I am trying to create a tabbar that works similarly to the browser tabs. Each tab loads a module. I am trying with mat-tab-nav-bar. Opening a new tab and setting it active as well as switching back and forth between tabs works fine. Closing a tab works and the tab is deleted from the array. Unfortunately, I cannot make the previously opened tab or the tab next to the closed tab active again and load the module. I put the last loaded and active page into the sessionStorage and load this page after a reload in the ngOnInit() function.

Angular and TypeScript are still new to me and I haven't gained much experience yet.

I have taken this example as a template. I also tried with this example, but I could not load any modules and with mat-tab-nab-bar it worked fine. https://stackblitz.com/edit/angular-zzehu6?file=src%2Fapp%2Ftab-group-dynamic-example.html

If a tab is to be deleted, the onRemoveTab() event is triggered. There I loop over the tabs and as soon as the tab to be deleted is found, I remove it from the Tabs array and set the previous tab in the FormControler as Active (or try to set it Active). I also save this tab in the sessionStorage. The result is that only the deleted tab is removed, but the previous tab is not set active and the module is not reloaded. How can I make this happen? Does anyone have an idea?

Here is my code. Please let me know if you need more information.

tabbar.component.html

<div *ngIf="currentTab">
  <nav mat-tab-nav-bar>
    <a
      mat-tab-link
      *ngFor="let tab of tabs; let index = index"
      [routerLink]="tab.link"
      routerLinkActive="false"
      #rla="routerLinkActive"
      [active]="rla.isActive"
      (click)="onSelect(tab, index)"
      disableRipple
    >
      {{tab.name}}
      <button 
        mat-icon-button 
        (click)="onRemoveTab(tab.id, index)" 
        [disabled]="tabs.length === 1"
      >
        <mat-icon style="transform: scale(0.8);">close</mat-icon>
      </button>
    </a>
  </nav>
</div>

<div class="content">
  <ng-content></ng-content>
</div>

tabbar.component.ts

import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';

import { SidenavRouteInterface } from './data';

@Component({
  selector: 'tabbar',
  templateUrl: './tabbar.component.html', 
})
export class TabbarComponent implements OnChanges, OnInit {
  selected = new FormControl(0);
  tabs: SidenavRouteInterface[] = [];
  sessionKey = 'currentTab';
  previousTab: SidenavRouteInterface | undefined;
  

  onSelect(router: SidenavRouteInterface, index: number) {
    sessionStorage.setItem(this.sessionKey, JSON.stringify(router));
    this.selected.setValue(router.id);
  }

  onRemoveTab(tabId: number, index: number) {
    this.tabs.forEach((tab) => {
      if (tab.id === tabId) {
        this.tabs.splice(index, 1);
        this.selected.setValue(this.previousTab?.id);

        sessionStorage.setItem(this.sessionKey, JSON.stringify(this.previousTab));
      } else {
        this.previousTab = tab;
      }
    });

    return false;
  }
}

sidenav-route.model.ts

export interface SidenavRouteInterface {
  id: number;
  name: string;
  link: string;
  icon?: string;
}

An example of how a tab in the array can look.

tabs: SidenavRouteInterface[] = [
  { id: 6, name: 'Document', link: 'document' },
  { id: 7, name: 'Reference', link: 'reference' },
];

enter image description here

Result:

enter image description here


Solution

  • this.router.navigate([this.previousTab.link]) does the trick.

    onRemoveTab(tabId: number, index: number) {
      this.tabs.forEach((tab) => {
        if (tab.id === tabId) {
          this.tabs.splice(index, 1);
          this.selected.setValue(this.previousTab?.id);
          this.router.navigate([this.previousTab.link]);
    
          sessionStorage.setItem(this.sessionKey, JSON.stringify(this.previousTab));
        } else {
          this.previousTab = tab;
        }
      });
    
      return false;
    }