[FIXED] PrimeNG TabView – Open Tab based on URL

Issue

Am using PrimeNG’s TabView component for a set of Tabs – Home, Appointments, Orders.

The appointments and orders tabs, have a list of links, which navigate to the individual appointment or order, these pages are separate routes/pages, they do not open in the tab.

The first issue is when the user hits the back button, they are taken to the Home Tab by default which is the first tab. The second issue, we need to make it possible for the user to share a link directly to the appointments tab or orders tab.

For both these asks, seems like putting a URL id – "app/main#home" or "app/main#appointments" or a query param : "app/main?tab=home","app/main?tab=appointments" would be good?

I wasn’t sure where to be on the ID option, the query param sounded more doable – with a route definition and programmatically selecting the index in ngOnInit.

Does PrimeNG provide something out of the box for this?

Edit: Using Angular 11 with PrimeNG 11.4.4

<p-tabView>
  <p-tabPanel header="Home">
    Summary
  </p-tabPanel>
  <p-tabPanel header="Appointments">
    <ng-template pTemplate="content">
      Table with Appointments - links take to Appointment details page.
    </ng-template>
  </p-tabPanel>
  <p-tabPanel header="Orders">
    <ng-template pTemplate="content">
      Table with Appointments - links take to Order details page.
    </ng-template>
  </p-tabPanel>
</p-tabView>

Solution

Concept

  1. Use ActivatedRoute to retrieve query params for tab.
  2. Get the tab index by comparing the param tab with headerName of tabView.tabs.
  3. Assign [(activeIndex)] with the tab index in (2).

Solution

main.component.html

<p-tabView #tabView 
  (onChange)="onChange($event)" 
  [(activeIndex)]="selectedTabIndex">
  ...
</p-tabView>

main.component.ts

import {
  AfterViewInit,
  ChangeDetectorRef,
  Component,
  ViewChild
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { TabView } from 'primeng/tabview';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css']
})
export class MainComponent implements AfterViewInit {
  selectedTabIndex: number = 0;

  @ViewChild('tabView') tabView!: TabView;

  constructor(private route: ActivatedRoute, private cdr: ChangeDetectorRef) {}

  ngAfterViewInit() {
    this.route.queryParams.subscribe(params => {
      this.selectedTabIndex = this.getTabIndex(params['tab']);

      this.cdr.detectChanges();
    });
  }

  getTabIndex(tabName: string): number {
    // Default tab: 0 when tabName is null or undefined
    if (!tabName) return 0;

    let selectedIndex = this.tabView.tabs.findIndex(
      x => x.header.toLowerCase() === tabName.toLowerCase()
    );

    if (selectedIndex > -1) return selectedIndex;

    // Default tab: 0 when tabName is not exist
    return 0;
  }

  onChange(event) {
    this.selectedTabIndex = event.index;
  }
}

Sample Solution on StackBlitz


References

PrimeNG TabView

Answered By – Yong Shun

Answer Checked By – Marie Seifert (Easybugfix Admin)

Leave a Reply

(*) Required, Your email will not be published