We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Dynamic tabs with content

Hello,

I need to add tabs and tab content dynamically into tabPanel. How can I achieve that?

                            <ej-tab id="tabsample">
                                <ul>
                                    <li><a rel='nofollow' href="#home" >Home</a></li>
                                </ul>
                                <div id="home" style="background-color: deeppink">
                                    <h1>Welcome! This is Home tab..</h1>     
                                </div> 
                            </ej-tab>

I can add tab dynamically like this:             
                              var tabObj = $("#tabsample").data("ejTab");
                              tabObj.addItem("#dynamicTab", "dynamic content", 2, "myClass", 2);

But how can I add content (dynamically)?
                               <div id="dynamicTab">
                                    <h1>Welcome Dynamic tab! </h1>     
                                </div> 

Also, I need that heightAdjustMode would be ''fill' for each tab.


P.S. Content can't be hardcoded into HTML. I need to be able to add it dynamically.




22 Replies

GG Gopi Govindasamy Syncfusion Team January 2, 2017 12:50 PM UTC

Hi Me 

We have checked your scenario for “new tab and content added dynamically in angular 2”, We can add the tab dynamically by using addItem() public method.  
 
Add code snippet here 

 

  
Regards, 
Gopi G   



ME Me January 2, 2017 08:59 PM UTC

Hey, thanks! However it works only for simple html, but not for angular / syncfusion components. How could I add something like this:

var content= "<div id='dynamicTab'> <myCustomList></myCustomList> </div>";

Also, is there a way to remove that HTML after tab is closed? Moreover can I specify particular tab to have / not have close button?


P.S. A bit disappointment that Syncfusion haven't implemented such an important functionality for TabPanel :/ 


GG Gopi Govindasamy Syncfusion Team January 3, 2017 09:24 AM UTC

Hi Me,    
  
We have checked your scenario. You can dynamically add ej component and the provided content to new tab items. We have prepared a sample for your requirement and attached the sample link below.    
  
  
In the tab control, we have provided showCloseButton property to show the close button icon. If you click the icon, the particular tab will be closed and the tab will be removed from HTML attributes also removed automatically. By default, all tabs show close icon. If you need to show the close icon in a particular tab item only, you have to customize this. We have customized the tab in the above sample.    
  
We have implemented most of the feature. Please share the expected feature in tab control, so that we can consider it and implement it.    
  
Regards,    
Gopi G.   



ME Me February 1, 2017 11:58 AM UTC

Hello again.

Your solution kinda works, but it's not fully what I need. It only works with HTML and Syncfusion component. I would like to write a wrapper for ejGrid and add that component (dynamically, which will also be lazy loaded). However, as far as I saw I'm not able to do that, unless I use hard-coded divs.

I tried to use this method:

Tabpanel:

Hard coding containers for dynamic load:

Creating Tab:

Lazy loading component and inserting into container:


Have in mind I'm using SystemJS for that. That works, but only until I try to close a tab. When I close tab my created hard-coded divs are also removed and I'm not able to reuse them.
1. Is there a way to prevent content div removal after tab close button is clicked? (Tab itself still has to hide) 
2. After tab is cloused with id tabContent3, I'm not anymore able to create tab with same ID, why is that? :o

 tabObj.addItem('tabContent3', 'tabContent9', 6, null, 'tabContent3'); Create tab like this, close it and then try to create it again.

I get this error:


P.S. Tried to use $("#myMainTabPanel").data("ejTab").hideItem(1); - not working. I get no error, but nothing happens. Tried to change index too.


PO Prince Oliver Syncfusion Team February 2, 2017 04:52 PM UTC

Hi Me, 

Thanks for your update. 

Query 1: Is there a way to prevent content div removal after tab close button is clicked? (Tab itself still has to hide)   

In order to remove the content alone instead of entire div, you need to manually override the _tabDeleteClick method. Have a look at the following code snippet. 

ej.Tab.prototype._tabDeleteClick = function (args) { 
            if (this.model.enabled) { 
                var currentTab = $(args.target); 
                if (currentTab.closest("li").hasClass("e-active") && currentTab.hasClass("e-close")){ 
                    $(this.contentPanels[this.model.selectedItemIndex()]).html(""); 
                } 
            } 
        }; 


Query 2: After tab is cloused with id tabContent3, I'm not anymore able to create tab with same ID, why is that?  

We were not able to reproduce the issue at our end. Please provide us additional information along with an issue reproducing sample and replication steps, it would help us to isolate the root cause and provide a solution 

Regards, 
Prince 



ME Me April 6, 2017 02:29 PM UTC

Hello again,

I need to be able to dynamically create tabs and insert my custom written components. Again, tab's must be created dynamically not hardcoded into html. How can I achieve that?

This is code how I would like to insert component into newly, dynamically created tab (vcRef is viewContainerRef which I don't have because tabs must be created dynamically, runtime) :
          // Inputs need to be in the following format to be resolved properly
        let inputProviders = Object.keys(inputData).map((inputName=> {return {provide: inputNameuseValue: inputData[inputName]};});
        let resolvedInputs = ReflectiveInjector.resolve(inputProviders);

        // We create an injector out of the data we want to pass down and this components injector
        let injector = ReflectiveInjector.fromResolvedProviders(resolvedInputsvcRef.parentInjector);

        // We create a factory out of the component we want to create
        let factory = this.resolver.resolveComponentFactory(component);

        // We create the component using the factory and the injector
        let comp = factory.create(injector);

        // We insert the component into the dom container
        vcRef.insert(comp.hostView);

        this.tabComponents[tabId] = comp;




PO Prince Oliver Syncfusion Team April 9, 2017 01:37 PM UTC

Hi Me, 

Thank you for your update. 

We are unable to replicate your scenario with the provided code. Please provide us a simple sample explaining your requirement. It will help us understand your query requirement better and provide solution. 

Regards, 
Prince 



ME Me April 24, 2017 05:57 AM UTC

Here is your asked working sample (which has some bugs, for instance - can't change title when tab reused). Just bear in mind, my provided sample is kinda working, but it's not right. I'm looking for better, easier and cleaner solution. My main goal is to be able dynamically create tabs and then add into them my custom created ng2 components. Not Syncfusion component, but my custom created component (which might have syncfusion component). You should understand what I need by checking sample out.P.S. Node_Modules folder excluded because of the file size, but I added it here: http://www74.zippyshare.com/v/xnoKpJXp/file.html


ME Me replied to Me April 24, 2017 06:00 AM UTC

Here is your asked working sample (which has some bugs, for instance - can't change title when tab reused). Just bear in mind, my provided sample is kinda working, but it's not right. I'm looking for better, easier and cleaner solution. My main goal is to be able dynamically create tabs and then add into them my custom created ng2 components. Not Syncfusion component, but my custom created component (which might have syncfusion component). You should understand what I need by checking sample out.P.S. Node_Modules folder excluded because of the file size, but I added it here: http://www74.zippyshare.com/v/xnoKpJXp/file.html

Attachment again.

Attachment: angular2seedsmaster_9d83b890.zip


PO Prince Oliver Syncfusion Team April 24, 2017 01:02 PM UTC

Hi Me, 

Thank you for your update. 

We checked the sample you shared. In order to dynamically create tabs with content, you can use the contentPanel from tab object and set the innerHtml content. Refer to the following code snippet. 

tabObj["contentPanels"][tabCount].innerHTML = "<div #" + tabId +"></div>"; 

  
ViewContainerRef will not be accessible for dynamically rendered div element and you cannot assign it dynamically. Hence the error will be thrown. So, you need to predefine the reference div elements if you need to use it as ViewContainerRef to render the ng2 components in them. 


Please note we have excluded the node_modules folder from the sample. 

Regards, 
Prince 



ME Me April 25, 2017 06:53 AM UTC

Echh.. That limitation really puts brackets on :| Looks like my current solutions is the best one, for a now.. Another related question: when I hide and show tab I need it to appear in the back of the tabs row, like a newly created tab. How can I do that? (Again, have a look into my provided sample as it's that one which I would like to upgrade)



PO Prince Oliver Syncfusion Team April 26, 2017 11:57 AM UTC

  
Hi Me,   
  
Thank you for your update.   
  
By default, in our tab control when the tab item is hidden and then shown, it will appear in the same position. To hide the item and show it in the last position, you need to manually remove the <li> element of the hidden tab and place it in the last. Kindly refer to the following code snippet.   

onHide(args) 
    { 
         var tabObj = this.gpTabPanel.widget; 
         var tabLi = tabObj["element"]["find"]("li"); 
        tabObj["hideItem"](1); 
        tabObj["items"][1]["setAttribute"]("style","display:none;"); 
        tabLi[tabObj["items"]["length"]-1]["parentNode"]["append"](tabLi[1]); 
      } 
//In the above method, we are hiding the second tab item and displaying it in last position  

We have attached the modified sample, kindly refer to the following link for the sample:  

Regards, 
Prince 



ME Me June 20, 2017 12:56 PM UTC

Hey,


I tried to implement your solution, but I get weird behavior: After moving old tab to the back of the row, on mouse over a tab it sets 'Exit'  button visibility for the previous tab (check picture):

After I add new tab normally, it fixed 'X' button visibility issues, bu then it shows two active tabs at the same time:



Any solution?






ME Me June 20, 2017 01:18 PM UTC

Moreover, after you close those two new tabs and create new one, some of the old dissapears until you again, create a few more new tabs and then everything seems to work ok.

Checked your provided sample, has same bugs.



PO Prince Oliver Syncfusion Team June 21, 2017 11:11 AM UTC

Hi Me,   
  
Thank you for your update.   
  
In the previous solution, we have provided the steps to move the <li> element to last while hiding. The changes done hasn’t been updated in the internal variables that hold the tab items. So, when the hover handler is called the close icons are displayed for items in their previous position. To overcome this, we need to refresh the variables by calling the internal _itemsRefreshing method and triggering the click for the active item updates the changes in the control thus fixing the multiple active item behavior. You need to refresh the items in both hide and show method. Kindly refer to the following code snippet.   

onHide(args) 
{ 
    var tabObj = this.gpTabPanel.widget; 
    var tabLi = tabObj["element"]["find"]("li"); 
    if(tabObj["items"]["length"]<=1){ 
    alert("Add more Tabs"); 
    }else{ 
    tabObj["hideItem"](1); 
    tabObj["items"][1]["setAttribute"]("style","display:none;"); 
    tabLi[tabObj["items"]["length"]-1]["parentNode"]["append"](tabLi[1]); 
       tabObj["_itemsRefreshing"](); 
       tabObj["items"]["parent"]()["find"](".e-active")["trigger"]("click"); 
    } 
} 
 
onShow(args) 
{ 
    var tabObj = this.gpTabPanel.widget; 
    var tabLi = tabObj["element"]["find"]("li"); 
    if(tabObj["items"]["length"]<=1){ 
    alert("Add more Tabs"); 
    }else{ 
    tabObj["showItem"](1); 
    tabObj["items"][1]["removeAttribute"]("style"); 
       tabObj["_itemsRefreshing"](); 
       tabObj["items"]["parent"]()["find"](".e-active")["trigger"]("click"); 
    } 
} 

Regards, 
Prince 



ME Me June 22, 2017 05:08 PM UTC

Hey,

Your provided code is working, but after that two code-rows is executed, content gets mixed up. Checked tab and content Ids - everything is fine (see image), but visually wrong content is shown. If your provided code is commented out, content shows fine, but there are those bugs with tabs then. Any solution?

If I comment out your provided code (see image below), content won't mix up and is shown fine. You can test it by commenting out provided code in two places: createNewTab and onBeforeTabItemRemvove.


You can reproduce bug by following these steps:

1. Create 4 tabs (GridComponent, GridComponentA, GridComponentB, GridComponentC)
2. Close 2 ar 3 of them (Don't close Home tab, that one is not implemented - it will stay open all the time)

3. Create closed tabs again. (If tab with that component is already opened, it will be automatically focused, otherwise created and moved to the back).


P.S. I attached working sample.


Attachment: ng2tabsample_f5de1c50.rar


ME Me June 22, 2017 05:11 PM UTC

Once again, to clarify problem: after code (which updates tab items internally) is executed, wrong content is shown within tabs. This won't happen if I don't execute your provided code. Tabs has correct content ids, so this is not a case. You should easily see that in my provided sample, as every grid has different headers by letter (A, B,C or none). 



PO Prince Oliver Syncfusion Team June 23, 2017 12:24 PM UTC

Hi Me,   
  
Thank you for sharing your sample.   
  
In the show method, we can use the internal refresh method to update the content panels in accordance with the changes done in the tab headers. Through this way, we can avoid the wrong content for the tabs. Kindly refer to the following code snippet.   

// Showing tab 
  tabObj["showItem"](tabId); 
  tabObj["items"][tabId]["removeAttribute"]("style"); 
//this.myTabPanel.widget.showItem(htId); 
//this.myTabPanel.widget.element.ejTab({hiddenItemIndex: this.hiddenTabs }); 
// Moving tab to the back of tabs row 
tabElements[tabId]["parentNode"]["append"](tabToShow); 
// Refreshing tabs 
tabObj["_itemsRefreshing"]();  
tabObj["items"]["parent"]()["find"](".e-active")["trigger"]("click");  
tabObj["_refresh"](); 

  
We have attached the modified sample for your convenience, kindly refer to the following link for the sample: http://www.syncfusion.com/downloads/support/forum/128048/ze/ng2tabsample_f5de1c50104942926 

Regards, 
Prince 



ME Me June 23, 2017 03:09 PM UTC

Cheers - that works! Looks like we are almost there.. A few more questions:
1. After 'X' is clicked on tab and onBeforeTabRemove() method is executed, how can I focus last tab in a tab row? showItem() seems not to be working...

2. That code you provided me, is there any documentation on that I can look into?





PO Prince Oliver Syncfusion Team June 27, 2017 07:33 AM UTC

Hi Me, 

Thank you for your update. 

Query 1. After 'X' is clicked on tab and onBeforeTabRemove() method is executed, how can I focus last tab in a tab row? showItem() seems not to be working...  

Response: To focus the last tab, we need to use the selectedItemIndex property. Kindly refer to the following code snippet.   

var tabObj = this.myTabPanel.widget.element.ejTab("instance");  
tabObj["setModel"]({ selectedItemIndex : tabObj["items"]["length"] - 1}); //To select the last tab 


Query 2. That code you provided me, is there any documentation on that I can look into? 

Response: We have provided a specific solution for your requirement by altering the default behavior of the tab and overriding the internal methods. Hence it is not documented.   

Regards, 
Prince 



ME Me June 27, 2017 12:27 PM UTC

Hey,

Your provided code is not working. Something else is missing again?



PO Prince Oliver Syncfusion Team June 28, 2017 12:17 PM UTC

Hi Me, 

Thank you for your update. 

We have to use setTimeout method to select the last tab item, because the selected items gets reset in the further execution of script in zone.js file after the onBeforeTabRemove() method. Kindly refer to the following code snippet. 

//selecting the last tab item after hiding 
setTimeout(()=>{    
    tabObj["setModel"]({ selectedItemIndex : tabObj["items"]["length"] - 1}); 
},1); 

  
We have attached the sample, kindly refer to the following link for the sample: http://www.syncfusion.com/downloads/support/forum/128048/ze/ng2tabsample1335150324 

Regards, 
Prince 


Loader.
Up arrow icon