6

I'm on a project where I need to use a p-tabView. A new p-tabPanel is to be created when clicking on a button in the p-tabView.

How can I dynamically add new panels to a p-tabView?

Antikhippe
  • 6,316
  • 2
  • 28
  • 43
Kutas Tomy
  • 349
  • 2
  • 7
  • 18
  • 1
    Please provide that what you have tried so far – Milan Malani Sep 08 '16 at 10:32
  • I tried to modify the DOM adding something like:
    to the tabWiev. The DOM is modified but something wrong and the panel is not visible.
    – Kutas Tomy Sep 08 '16 at 12:31
  • I also tried to find a method of the component wich is adding panels to the component, but no succcess. The component has no method wich is adding new panels. I used this solution to call component methods: http://stackoverflow.com/questions/31013461/call-a-method-of-the-child-component – Kutas Tomy Sep 08 '16 at 12:35

3 Answers3

8

I figured out a way. I am using ngFor to control the # of tabPanel.

My component.ts code will manipulate myModel.leads. Thus, the number of tabPanel will change accordingly.

<!--Lead-->
<p-tabView  >  
  <p-tabPanel [selected]="i==0" *ngFor="let lead of procedureDetail.leads; let i = index" header="lead {{i+1}}"  >
           <div id="{{lead.id}}" class="my_dynamica_lead_tabPanel"> <!-- I can add content to this div with tabView.onChange() api -->
          {{lead.id}} - {{i}}
           </div>
           <div class="row">
              <div class="col-md-3">
                 Date:
              </div>
           <div class="col-md-9">
              <p-calendar [style]="{'width':'180px'}" [monthNavigator]="true" [yearNavigator]="true" yearRange="1900:2020" name="lead.{{i}}.date" [(ngModel)]="lead.date" [showIcon]="true" ></p-calendar> 
          </div>
       </div>

   </p-tabPanel>
</p-tabView> 

Note - If you forget to include [selected] attribute while using *ngFor in p-tabPanel. You will get following error

TabPanel.html:2 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'none'. Current value: 'block'.
Mohan Ram
  • 8,345
  • 25
  • 81
  • 130
jeff hu
  • 81
  • 1
  • 3
  • 1
    I'm doing the same way, there's one thing: I'm experiencing memory leaks when I remove elements form the arraybinded to the ngFor (e.g the procedureDetail.leads), the Nodes are not removing from the DOM... – user2010955 Mar 28 '18 at 06:32
0

I just found a possible sollution for this problem. Making a list of object type of TabPanel.

tabs: TabPanel = [{header: 'tabbdfd', selected : false, disabled : false ,closable : true, closed : false}, {header: '3333', selected : false, disabled : false ,closable : true, closed : false}];

The component looks like:

<p-tabView>  
     <p-tabPanel *ngFor="#tab of tabs" [header]="tab.header" >
            <CONTENT>   
    </p-tabPanel>
</p-tabView> 

Maybe will be usefull for somebody :)

Kutas Tomy
  • 349
  • 2
  • 7
  • 18
  • 1
    This certainly works to create a dynamic set of tabs, but the content is not dynamic. So it's not very useful to have a bunch of tabs all with the same content. – Mutmansky Oct 24 '16 at 16:14
  • On tab selection/change I reloaded from a map [key == tabHeader] the selected panel content. In this way changing the tabs, the content is also changed. – Kutas Tomy Apr 19 '17 at 11:56
  • Understood, but how did you populate that map? I assume you still knew what content you needed to load ahead of time so you could populate that map appropriately. In my situation, the contents of the tabs are determined at run time. That is, there's a database table that tells me what tabs I need to have in the application. So after my application starts up, I read that list of tabs in from the database and I create them using ComponentResolver. Sounds like your situation is different. – Mutmansky Apr 20 '17 at 12:44
  • My situation is pretty the same. I also have my application connected to a database. Basically, the map is populated when the app starts up. I'm calling some REST services to get data loaded. I didn't use any Component Resolver. I have a simple GUI, only a data table which has some filters. – Kutas Tomy Apr 20 '17 at 13:27
  • Maybe there's something missing from your answer then. You put in the as if it's a place holder, so I'm assuming that content is just statically defined in the template. I could see how the data within that could be different based on what's in your map, but the itself is the same. Correct? If not, how is the content loaded into the DOM based on what's in your map? – Mutmansky Apr 21 '17 at 18:30
-1

you can do like below:

<ng-template pTemplate="header"> Header Text </ng-template>

Waqas
  • 49
  • 4