'Dynamically Add tabPanel to tabView in PrimeNg

I wanted to have a 'Add Tab' button, on clicking that button i want to add a new Tab(tabPanel) to existing list of tabView. Till now i am able to achieve the addition of new tab on clicking a 'Add Tab' button but i am not sure how to add the dynamic html content to the tab.

appComponent.html

<button pButton (click)="addTab()" label="selected header"></button>
<p-tabView (onChange)="onChange($event)" [activeIndex]="selectedIndex">
  <p-tabPanel header="first" [selected]="true">
    Hello1
  </p-tabPanel>
  <p-tabPanel header="second" cache="false">
    hello2
  </p-tabPanel>
</p-tabView>

app.component.ts

import {Component, ViewChild, ViewContainerRef} from '@angular/core';
import {TabView, TabPanel} from 'primeng/primeng';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor(private viewContainerRef: ViewContainerRef) {
  }

  @ViewChild(TabView) tabView: TabView;

  addTab() {
    const tab: TabPanel = new TabPanel(this.viewContainerRef);
    tab.header = 'Tab3';
    tab.closable = true;
    this.tabView.tabs.push(tab);
  }
}


Solution 1:[1]

This is what worked for me. I took inspiration from Mr. Victor Baydun's answer.

import { Component, HostBinding, QueryList, ViewChild, ViewContainerRef } from "@angular/core";
import { TabPanel, TabView } from "primeng/tabview";

@Component({
  ...
})
export class MyTabClass {

  @ViewChild("tabsContainer", { static: true, read: ViewContainerRef }) tabsContainer!: ViewContainerRef;

  ngAfterViewInit() {

    const tabView = this.tabsContainer.createComponent<TabView>(TabView);
    const tabPanel1 = new TabPanel(tabView.instance, this.tabsContainer, tabView.changeDetectorRef);
    const tabPanel2 = new TabPanel(tabView.instance, this.tabsContainer, tabView.changeDetectorRef);
    const queryList = new QueryList<TabPanel>(false);

    tabPanel1.selected = true;

    queryList.reset([tabPanel1, tabPanel2]);
    
    tabView.instance.tabPanels = queryList;
    tabView.instance.tabs.push(tabPanel1, tabPanel2);
    tabView.instance.initTabs();
  }
}
<ng-container #tabsContainer></ng-container>

Solution 2:[2]

import {Component, ViewChild, ViewContainerRef, ComponentFactoryResolver} from '@angular/core';
import {TabView, TabPanel} from 'primeng/primeng';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor(private componentFactoryResolver: ComponentFactoryResolver, 
      private viewContainerRef: ViewContainerRef) {
  }

  @ViewChild(TabView) tabView: TabView;

  addTab() {
    let nTabs = this.tabView.tabs.length;
    const tab: TabPanel = new TabPanel(this.viewContainerRef);
    tab.header = 'Tab' + (nTabs+1);
    tab.closable = true;
    const component: any = <some component>;
    const factory = this.componentFactoryResolver.resolveComponentFactory(component);
    this.viewContainerRef.createComponent(factory);
    this.tabView.tabs.push(tab);
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pavel_K
Solution 2