Adding and Removing Tabs with jQuery and jQuery UI

Posted on Apr 22, 2009

Using the tabs UI functionality in jQuery can be amazingly easy, assuming you just want to convert some basic content into a tab layout. However, once you start trying to dynamically add/remove tabs (as you will often run into on advanced layouts) it gets a little hairy. As with everything injQuery UI in my experience so far, you can do what you want its just neither straightforward or well documented. This tutorial will show the ways you can add/remove or show/hidejQuery tabs and some of the gotchas and drawbacks associated with those methods.

Adding and Removing Tabs
The tab functionality in jQuery UI includes methods for adding and removing tabs. To add a tab you simply do $("#mytabs").tabs("add","tabContent.htm","New Tab") for a tab that is populated via Ajax or $("#mytabs").tabs("add","#tabContent","NewTab") for a tab that is populated by the contents of a Div on that page, for instance. Killing a tab is also straightforward, $("#mytabs").tabs("remove",1). Nonetheless, there are a number of "gotchas" when using this.

Firstly, there doesn't appear to be any built in method to get what tabs already exist within any tabs list or which tab is selected(other than searching the DOM). In addition, if you add a tab in this manner, populate it with the contents of a local div and then remove it, that content cannot be re-added (I assume because that portion of the DOM is blown away when it is removed). If you need to remove and add the content again, you will need to load the content via the Ajax method. This would be fine, except that if you had populated content or selected an option, for example, this will not be retained when the content is reloaded. For example, in sample code (see below), I have a select box which, when reloaded, will obviously always reset back to the default option. This isn't always an acceptable solution.

Showing and Hiding Tabs
Unfortunately, there is also no built-in method for hiding/showing specific tabs via the tabs UI API. In addition, if you simply hide the div content of the tab, it will not hide the tab. In fact, to hide a tab, you need to hide the list item associated with that tab rather than the Div content. In this way the tab always exists, but is simply displayed conditionally and any changes to the content of that tab, like our select box, will be retained.

While you can parse through the DOM using jQuery and pick a tab to show or hide, in order to show/hide specific tabs you will likely need to assign each list item a unique ID, as in the example code below. Once your tab list item has a unique ID, you can simply hide it by using $("#tabs-1-tab").css("display","none") or $("#tabs-1-tab").css("display","list-item") to show it again. One trick in this case is that if you hide the currently selected tab, you will need to refresh the displayed content by deliberately selecting another tab or the content of the closed tab will still show. You can easily do this using a built in method of tabs, $("#mytabs").tabs("select",0), which would select the first tab, for example.

Helper Methods
If you look at the example code below, you'll see some helper methods that I am using to handle hiding/showing tabs. For example I have a method I use often when I want to change which tabs are displayed that uses one line to hide all the tabs, after which I selectively display the tabs I want - $("#tablist").children().css("display","none"). Also, you can make a single method to hide/show tabs by passing in the tab ID string as in theopenTab () method below. This also takes care of selectively hiding all the other tabs and ensuring that the newly opened tab is selected. These aren't the most complex examples of helper methods for hiding/showing tabs but it should give you some guidance on where to go from here.

Going Forward
Personally, I hope that the jQuery UI tabs implementation adds some built-in methods for handling things like hiding/showing tabs, getting the selected tab, and getting an array of tabs that exist (rather than simply parsing the DOM that is). Still, hopefully this post provides some level of documentation on how to achieve some of these results via alternative methods as I wasn't able to find much out there yet.

Full code for the tabs sample page:

<html>
<head>
<title>jQuery UI Tabs Demo</title>

<link type="text/css" href="css/smoothness/jquery-ui-1.7.1.custom.css" rel="stylesheet" />

<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery-ui-1.7.1.custom.min.js"></script>

<script type="text/javascript">
function init() {
   $("#mytabs").tabs();
   // wipe all the tabs so we can programatically show the ones we want
   removeAllTabs();
   // if {condition}, then show relevant tab. this is just for example purposes
   if (true) {
      $("#tabs-1-tab").css("display","list-item");
   }
   // now show the tabs area
   $("#mytabs").css("display","block");
}

function openTab(tabNum,closeOthers) {
   if (closeOthers != false) {
      removeAllTabs();
   }
   $("#tabs-"+tabNum+"-tab").css("display","list-item");
   $("#mytabs").tabs("select",tabNum-1);
}

function removeAllTabs() {
   $("#tablist").children().css("display","none");
}

function createTab4() {
   // this will add a tab via the standard method
   $("#mytabs").tabs("add","#tabs-4","Fourth Tab");
   $("#tabs-4").css("display","block");
}

function removeTab4() {
   // this will add a tab via the standard method. part of the problem here is I don't know the index...just assuming its on the end
   $("#mytabs").tabs("remove",$("#mytabs").tabs("length")-1);
   // reselect the 2nd tab or it will show tab 3
   $("#mytabs").tabs("select",1);
}

function createTab5() {
   // this will add a tab via the standard method
   $("#mytabs").tabs("add","tabs5.htm","Fifth Tab");
}


function removeTab5() {
   // this will add a tab via the standard method. part of the problem here is I don't know the index...just assuming its on the end
   $("#mytabs").tabs("remove",$("#mytabs").tabs("length")-1);
   // reselect the 2nd tab or it will show tab 3
   $("#mytabs").tabs("select",1);
}

$(document).ready(init);
</script>
</head>
<body>
<div id="mytabs" style="display:none;">
   <ul id="tablist">
      <li id="tabs-1-tab"><a href="#tabs-1">First Tab</a></li>
      <li id="tabs-2-tab"><a href="#tabs-2">Second Tab</a></li>
      <li id="tabs-3-tab"><a href="#tabs-3">Third Tab</a></li>
   </ul>
   <div id="tabs-1">
      <p>This is my first tab. It should show by default when the page is ready.</p>
      <p>If you select option 2 in this select box, it will still be selected when reopened</p>
      <p><select name="foo">
         <option>Option 1</option>
         <option>Option 2</option>
      </select></p>
      <p>Click the button to open tab 2 and close this tab.</p>
      <input type="button" name="openTab2" value="Open Tab 2" onclick="openTab(2)" />
   </div>
   <div id="tabs-2">
      <p>This is my second tab. It shows when you click the button in tab 1. Tab 1 and 2 should never appear together.</p>
      <p>Click the button to open tab 3. This tab will remain open.</p>
      <input type="button" name="openTab3" value="Open Tab 3" onclick="openTab(3,false)" />
      <p>Click this button to "create" tab 4 using the create method on a local div.</p>
      <input type="button" name="createTab4" value="Create Tab 4" onclick="createTab4()" />
      <p>Click this button to "create" tab 5 using the create method using ajax for content.</p>
      <input type="button" name="createTab5" value="Create Tab 5" onclick="createTab5()" />
   </div>
   <div id="tabs-3">
      <p>This is my third tab tab. It shows when you click the button in tab 2. It can show along with tab 2.</p>
      <p>Click the button to open tab 1 again. Any other open tabs will close.</p>
      <input type="button" name="openTab1" value="Open Tab 1" onclick="openTab(1)" />
   </div>
</div>
<div id="tabs-4" style="display:none;">
   <p>This tab is created using the create method but when I remove you won't be able to add it again with this content.</p>
   <p>Click the button to kill this tab.</p>
   <input type="button" name="killTab4" value="Kill This Tab" onclick="removeTab4()" />
</div>
</body>
</html>

Code for Tab5.htm:

<div id="tabs-5">
   <p>This is my fifth tab. It should show by default when the page is ready.</p>
   <p>If you select option 2 in this select box, it will reset when the tab is reloaded</p>
   <p><select name="foo">
      <option>Option 1</option>
      <option>Option 2</option>
   </select></p>
   <p>Click the button to kill this tab.</p>
   <input type="button" name="killTab5" value="Kill This Tab" onclick="removeTab5()" />
</div>

Comments

Al Macmillan Hi,

I think you are addressing something I have struggled to find docs for on the web. A really useful post! However, you've provided no css for your example so I can't test it. Could you not include the css in the header or set up a demo? Would be really helpful.

Thanks!

Posted By Al Macmillan / Posted on 06/24/2009 at 9:10 AM


Al Macmillan I'm an idiot! Didn't know JQuery UI had css styles. Whoops. Brilliant post

Posted By Al Macmillan / Posted on 06/24/2009 at 11:02 AM


fengyc This is very helpful to me ,thanks a lot!

Posted By fengyc / Posted on 07/14/2009 at 1:08 AM


Dhurai Where can I found download the files,
css/smoothness/jquery-ui-1.7.1.custom.css
jquery-1.3.2.min.js

Posted By Dhurai / Posted on 09/11/2009 at 7:58 AM


Dhurai I got the .js files from jquery.com but not the CSS file.
While trying to run this example by simply copy and past, my program was not running. What may be the problem can u please suggest?

Posted By Dhurai / Posted on 09/11/2009 at 8:20 AM


Brian Rinaldi @Dhurai - those CSS files should come with the jQueryUI downloads (not the standard jQuery download).

Posted By Brian Rinaldi / Posted on 09/11/2009 at 10:46 AM


SD.Plox Thank you very much RemoteSynthesis.

I was looking for a while this. (is incredible how difficult turns it out to hide the blessed tab : P)

Posted By SD.Plox / Posted on 03/09/2010 at 2:21 PM


Aamir Afridi A quick demo

Posted By Aamir Afridi / Posted on 03/26/2010 at 10:13 AM


Aamir Afridi Sorry forgot to mention the link in my last coment
http://jsbin.com/obiko/3

Posted By Aamir Afridi / Posted on 03/26/2010 at 10:14 AM


Per Ekström Here's a better way to find the tab to remove:

function removetab(tab_id) {
jQuery('#mytabs > div').each(function(n) {
if (this.id == tab_id) {
jQuery('#mytabs').tabs('remove',n);
}
});
}

Call by using removetab('tabs-4');

Hope that helped. :)

Posted By Per Ekström / Posted on 06/01/2010 at 4:02 AM


Ramanadham How to select second tab when page loding, insted of first tab.
Pls send me solution, present i am working on this.

Posted By Ramanadham / Posted on 09/22/2010 at 12:38 AM


Jacob Tabak Performed a long-shot google search and was directed to exactly what I needed. You saved me hours of trial and error. Thank you.

Posted By Jacob Tabak / Posted on 04/12/2011 at 8:48 PM


Steve Thanks!

Much better than the jQuery site. Very easy to hide / show various tabs, based on using the CSS.

You saved me a lot of time! :-)

Take care!

Posted By Steve / Posted on 05/02/2011 at 2:18 PM


Joel Hockey In more recent versions of jqueryui (1.8.7 onwards I think), adding #tabs-4 doesn't work unless #tabs-4 is a child of #mytabs

The code change is at: https://github.com/jquery/jquery-ui/commit/63ec1152d810a80596b195301ee3d2cd3d6a1776

Hopefully this helps someone else

Posted By Joel Hockey / Posted on 10/25/2011 at 5:54 PM


Yousuf Shaikh Amazing post. One thing I noticed (and I am presently working on this) was that you mentioned assigning an ID to a tab to show/hide them, but you make no mention how to assign an ID when a tab is created dynamically via .tabs("add"). Will try to find a workaround and post the solution here if it helps.

Once again, thanks for the succinct post.

Posted By Yousuf Shaikh / Posted on 11/22/2011 at 9:13 AM


nishu superb thanks :)

Posted By nishu / Posted on 11/28/2011 at 3:55 AM


Ben Really useful post, in addition to making sure that #tabs-4 was a child of mytabs, I found I also had to do "jQuery("#tabs-4").show();" otherwise the content was loaded into the tab but it retained display:none

Posted By Ben / Posted on 01/11/2012 at 9:29 AM


Mike B I'm doing some dynamic tab-hiding based on check-boxes from a previous tab...
For the tabs I don't want to display initially, I used <li class="ui-tabs-hide">
Now, the <a> tags already have IDs, right? So I have a checkbox whos click-events are:
function cbx_click() {
var chkd=$(this).is(':checked');
if (chkd)
$('#atag-2').parent().removeClass('ui-tabs-hide');
else
$('#atag-2').parent().addClass('ui-tabs-hide');
}

Hope this helps!

Posted By Mike B / Posted on 03/10/2012 at 6:29 PM


Rashid great plugin man!

Posted By Rashid / Posted on 03/13/2012 at 4:40 AM


Scott I added a button to each tab to close it. Here's a simple function to add to the button's click event.

var $tabs = $('#tabsID').tabs();
var selected = $tabs.tabs('option', 'selected');
$tabs.tabs('remove',selected);

Posted By Scott / Posted on 08/08/2012 at 5:50 PM


dhaval Love you boss.. you saved my couple of hours..
Thank you again.

Posted By dhaval / Posted on 09/17/2012 at 4:06 AM


Write your comment



(it will not be displayed)







About

My name is Brian Rinaldi and I am the Web Community Manager for Flash Platform at Adobe. I am a regular blogger, speaker and author. I also founded RIA Unleashed conference in Boston. The views expressed on this site are my own & not those of my employer.