# TabPanel 101

This page shows how to get started with Wijmo's TabPanel control.

## Getting Started

Using the TabPanel control is like using any Wijmo control:

1. Include the required scripts, either from local copies of from our CDN. For details, please see Referencing Wijmo in Your Applications.
2. Create elements on the page that will host the controls.
3. Initialize the controls passing the id of the host element as a parameter, followed by an optional initialization object.

The markup used to initialize TabPanel controls consists of one element per tab. Each child element contains two children: the tab header and the tab content.

We suggest you use anchor elements (tag a) for the tab headers because they are semantically more meaningful than plain div elements.

In this example, we added a "wj-state-active" class to the "America" pane markup. That defines the tab that is initially selected. Alternatively, we could have initialized the TabPanel's selectedIndex property in JavaScript.

HTML
<div id="tabGettingStarted"> <div> <a>Africa</a> <div> <ul> <li>Algeria</li> <li>Angola</li> <li>Benin</li> <li>Botswana</li> </ul> </div> </div> <div> <a class="wj-state-active"> America </a> <div> <ul> <li>Canada</li> <li>Chile</li> <li>Mexico</li> <li>United States</li> </ul> </div> </div> <div> <a>Asia</a> <div> <ul> <li>China</li> <li>Korea</li> <li>India</li> <li>Japan</li> </ul> </div> </div> <div> <a>Europe</a> <div> <ul> <li>Austria</li> <li>England</li> <li>France</li> <li>Germany</li> <li>Netherlands</li> <li>Switzerland</li> </ul> </div> </div> <div> <a>Oceania</a> <div> <ul> <li>Australia</li> <li>Fiji</li> <li>New Zealand</li> <li>Samoa</li> </ul> </div> </div> </div>
JS
var tabGettingStarted = new wijmo.nav.TabPanel('#tabGettingStarted');

#### Result (live):

Africa

- Algeria
- Angola
- Benin
- Botswana

America

- Canada
- Chile
- Mexico
- United States

Asia

- China
- Korea
- India
- Japan

Europe

- Austria
- England
- France
- Germany
- Netherlands
- Switzerland

Oceania

- Australia
- Fiji
- New Zealand
- Samoa

## Hosting Wijmo Controls

One of the main benefits of the TabPanel control is that it automatically updates any Wijmo controls it contains when a new tab is selected.

When using other tab controls, you must add code to refresh any Wijmo controls contained in the tabs.

HTML
<div id="tabWijmoControls"> <div> <a>FlexGrid</a> <div> <div id="theGrid"></div> </div> </div> <div> <a>FlexChart</a> <div> <div id="theChart"></div> </div> </div> <div> <a>Gauges</a> <div style="overflow:hidden"> <div id="theRadialGauge"></div> <div id="theLinearGauge"></div> </div> </div> </div>
JS
var tabWijmoControls = new wijmo.nav.TabPanel('#tabWijmoControls'); var theGrid = new wijmo.grid.FlexGrid('#theGrid', { itemsSource: getData() }); var theChart = new wijmo.chart.FlexChart('#theChart', { itemsSource: getData(), bindingX: 'country', series: [ { binding: 'sales', name: 'Sales' }, { binding: 'expenses', name: 'Expenses' }, { binding: 'downloads', name: 'Downloads' } ] }); var theRadialGauge = new wijmo.gauge.RadialGauge('#theRadialGauge', { min: 0, max: 100, value: 75, isReadOnly: false }); var theLinearGauge = new wijmo.gauge.LinearGauge('#theLinearGauge', { min: 0, max: 100, value: 75, isReadOnly: false }); function getData() { var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','), data = []; for (var i = 0; i < countries.length; i++) { data.push({ country: countries[i], sales: Math.random() * 10000, expenses: Math.random() * 5000, downloads: Math.round(Math.random() * 20000), }); } return data; }
CSS
.wj-tabpanel .wj-flexgrid, .wj-tabpanel .wj-flexchart, .wj-tabpanel .wj-radialgauge { height: 200px; border: none; }

#### Result (live):

FlexGrid
FlexChart
Gauges

## Creating TabPanels Programmatically

In some cases, you may want to add tabs to a TabPanel control programmatically rather than using HTML markup.

You can do this using the tabs property, which provides access to the collection of tabs in the TabPanel.

In this example, we add several Tab objects to the tabs collection. Each Tab object is defined by a header and a pane elements.

You can also use the tabs property to remove, modify, or reorder the tabs within the TabPanel.

HTML
<div id="tabInCode"> </div>
JS
var tabInCode = new wijmo.nav.TabPanel('#tabInCode'), url = 'http://services.odata.org/Northwind/Northwind.svc/', headers = 'Employees,Categories,Products,Customers'.split(','); tabInCode.tabs.deferUpdate(function () { // update only when done headers.forEach(function (header) { // create the tab header element var elHeader = document.createElement('a'); elHeader.textContent = header; // create the tab pane element var elPane = document.createElement('div'), elGrid = document.createElement('div'), grid = new wijmo.grid.FlexGrid(elGrid, { isReadOnly: true, itemsSource: new wijmo.odata.ODataCollectionView(url, header) }); elPane.appendChild(elGrid); // add the new Tab to the TabPanel tabInCode.tabs.push(new wijmo.nav.Tab(elHeader, elPane)); }); });

#### Result (live):

## Styling and CSS

You can customize the appearance of the TabPanel using CSS.

The TabPanel control has a simple layout, which makes it easy to style using CSS. For example, tabs appear above the content by default, but you can use CSS to change their position and show the below or vertically stacked, to the left or to the right of the content.

This example changes the appearance of the Tabs and lets you select the tab alignment and whether or not to use animation when switching tabs.

HTML
<div id="tabCss" class="custom-tab"> <div> <a>Africa</a> <div> <ul> <li>Algeria</li> <li>Angola</li> <li>Benin</li> <li>Botswana</li> </ul> </div> </div> <div> <a>America</a> <div> <ul> <li>Canada</li> <li>Chile</li> <li>Mexico</li> <li>United States</li> </ul> </div> </div> <div> <a>Asia</a> <div> <ul> <li>China</li> <li>Korea</li> <li>India</li> <li>Japan</li> </ul> </div> </div> <div> <a>Europe</a> <div> <ul> <li>Austria</li> <li>England</li> <li>France</li> <li>Germany</li> <li>Netherlands</li> <li>Switzerland</li> </ul> </div> </div> <div> <a>Oceania</a> <div> <ul> <li>Australia</li> <li>Fiji</li> <li>New Zealand</li> <li>Samoa</li> </ul> </div> </div> </div> <div> <label for="tabAlign"> Tab Alignment </label> <div id="tabAlign"></div> </div> <div> <label for="isAnimated"> isAnimated </label> <input id="isAnimated" type="checkbox" checked="checked"> </div> <div> <label for="customHeaders"> Custom Headers </label> <input id="customHeaders" type="checkbox"> </div> <div> <label for="tabsOnLeft"> Tabs on the Left </label> <input id="tabsOnLeft" type="checkbox"> </div>
JS
var tabCss = new wijmo.nav.TabPanel('#tabCss'); // toggle custom classes document.getElementById('tabsOnLeft').addEventListener('click', function (e) { wijmo.toggleClass(tabCss.hostElement, 'tabs-on-left', e.target.checked); }); document.getElementById('customHeaders').addEventListener('click', function (e) { wijmo.toggleClass(tabCss.hostElement, 'custom-headers', e.target.checked); }); // change tab alignment var tabAlign = new wijmo.input.ComboBox('#tabAlign', { itemsSource: 'Left,Center,Right'.split(','), selectedIndexChanged: function (s, e) { tabCss.hostElement.querySelector('.wj-tabheaders').style.textAlign = s.text; } }); // toggle animation document.getElementById('isAnimated').addEventListener('click', function (e) { tabCss.isAnimated = e.target.checked; });
CSS
/* custom-headers */ .wj-tabpanel.custom-headers .wj-tabpanes { border-top: none; } .wj-tabpanel.custom-headers .wj-tabheaders { background: black; color: white; } .wj-tabpanel.custom-headers .wj-tabheaders .wj-tabheader.wj-state-active { background: white; color: black; } .wj-tabpanel.custom-headers .wj-tabheaders .wj-tabheader:not(.wj-state-active) { font-weight: normal; } .wj-tabpanel.custom-headers .wj-tabheaders .wj-tabheader.wj-state-active:after { /* hide underline */ display: none; } /* tabs on the left*/ .wj-tabpanel.tabs-on-left > div{ display: flex; align-items: center; } .wj-tabpanel.tabs-on-left .wj-tabheaders { display: flex; flex-direction: column; min-width: 8em; border-right: 1px solid #ddd; } .wj-tabpanel.tabs-on-left .wj-tabpanes { display: flex; flex-grow: 1; border-top: none; overflow-x: hidden; }

#### Result (live):

Africa

- Algeria
- Angola
- Benin
- Botswana

America

- Canada
- Chile
- Mexico
- United States

Asia

- China
- Korea
- India
- Japan

Europe

- Austria
- England
- France
- Germany
- Netherlands
- Switzerland

Oceania

- Australia
- Fiji
- New Zealand
- Samoa

Tab Alignment
isAnimated
Custom Headers
Tabs on the Left

## Disabled and Invisible Tabs

You can disable or hide individual tabs using the Tab's isDisabled and isVisible properties.

HTML
<div id="tabDisableHide"> <div> <a>Africa</a> <div> <ul> <li>Algeria</li> <li>Angola</li> <li>Benin</li> <li>Botswana</li> </ul> </div> </div> <div> <a>America</a> <div> <ul> <li>Canada</li> <li>Chile</li> <li>Mexico</li> <li>United States</li> </ul> </div> </div> <div> <a>Asia</a> <div> <ul> <li>China</li> <li>Korea</li> <li>India</li> <li>Japan</li> </ul> </div> </div> <div> <a id="tab-europe" class="wj-state-disabled">Europe</a> <div> <ul> <li>Austria</li> <li>England</li> <li>France</li> <li>Germany</li> <li>Netherlands</li> <li>Switzerland</li> </ul> </div> </div> <div> <a id="tab-oceania">Oceania</a> <div> <ul> <li>Australia</li> <li>Fiji</li> <li>New Zealand</li> <li>Samoa</li> </ul> </div> </div> </div> <div> <label for="disableEurope"> Disable Europe </label> <input id="disableEurope" type="checkbox" checked> </div> <div> <label for="showOceania"> Show Oceania </label> <input id="showOceania" type="checkbox" checked> </div>
JS
var tabDisableHide = new wijmo.nav.TabPanel('#tabDisableHide'); // toggle Europe's disabled state document.getElementById('disableEurope').addEventListener('click', function (e) { tabDisableHide.getTab('tab-europe').isDisabled = e.target.checked; }); // toggle Oceania's visibility document.getElementById('showOceania').addEventListener('click', function (e) { tabDisableHide.getTab('tab-oceania').isVisible = e.target.checked; });

#### Result (live):

Africa

- Algeria
- Angola
- Benin
- Botswana

America

- Canada
- Chile
- Mexico
- United States

Asia

- China
- Korea
- India
- Japan

Europe

- Austria
- England
- France
- Germany
- Netherlands
- Switzerland

Oceania

- Australia
- Fiji
- New Zealand
- Samoa

Disable Europe
Show Oceania

## Detached Panels

The TabPanel has a built-in panel that shows the content of the selected tab. In some cases, you may want to display the content in a different element. To do that, simply hide the built-in content element and use the selectedIndexChanged event to update the content.

HTML
<div id="tabDetached"> <!-- tab without any content --> <div> <a>Africa</a> <div></div> </div> <div> <a>America</a> <div></div> </div> <div> <a>Asia</a> <div></div> </div> <div> <a>Europe</a> <div></div> </div> <div> <a>Oceania</a> <div></div> </div> </div> <p></p> <div class="panel panel-success"> <!-- separate div to show the content --> <div class="panel-heading"> <h3 id="detachedContent" class="panel-title"></h3> </div> </div>
JS
var tabDetached = new wijmo.nav.TabPanel('#tabDetached', { // show the content for the selected tab in a separate div selectedIndexChanged: function (s, e) { var div = document.getElementById('detachedContent'); div.innerHTML = 'Content for tab <b>' + s.selectedTab.header.textContent + '</b>...'; } }); // hide the built-in content area tabDetached.hostElement.querySelector('.wj-tabpanes').style.display = 'none';

#### Result (live):

Africa
America
Asia
Europe
Oceania

###

## Accessibility

The TabPanel implements WAI-ARIA accessibility guidelines. All tab elements have the proper role attributes as well as all applicable ARIA attributes.

The example below assigns unique IDs to the tab headers and panes, which the TabPanel automatically uses to generate "aria-controls" and "aria-labelledby" attributes.

The example also adds a "wj-state-active" class to the "America" pane in markup to define the tab that is initially selected. Without that, the first tab would have been selected by default.

Finally, the example shows the effect of the autoSwitch property, which affects how the control handles the tab and cursor keys. For a detailed discussion of this topic, please see the W3C ARIA practices and SimplyAccessible article.

HTML
<div id="tabAccessibility"> <div> <a id="hdr-africa"> Africa </a> <div id="pane-africa"> <ul> <li>Algeria</li> <li>Angola</li> <li>Benin</li> <li>Botswana</li> </ul> </div> </div> <div> <a id="hdr-america" class="wj-state-active"> America </a> <div id="pane-america"> <ul> <li>Canada</li> <li>Chile</li> <li>Mexico</li> <li>United States</li> </ul> </div> </div> <div> <a id="hdr-asia"> Asia </a> <div id="pane-asia"> <ul> <li>China</li> <li>Korea</li> <li>India</li> <li>Japan</li> </ul> </div> </div> <div> <a id="hdr-europe"> Europe </a> <div id="pane-europe"> <ul> <li>Austria</li> <li>England</li> <li>France</li> <li>Germany</li> <li>Netherlands</li> <li>Switzerland</li> </ul> </div> </div> <div> <a id="hdr-oceania"> Oceania </a> <div id="pane-oceania"> <ul> <li>Australia</li> <li>Fiji</li> <li>New Zealand</li> <li>Samoa</li> </ul> </div> </div> </div> <div> <label for="autoSwitch"> autoSwitch </label> <input id="autoSwitch" type="checkbox" checked="checked"> </div>
JS
var tabAccessibility = new wijmo.nav.TabPanel('#tabAccessible'); // toggle autoSwitch property document.getElementById('autoSwitch').addEventListener('click', function (e) { tabAccessibility.autoSwitch = e.target.checked; })

#### Result (live):

Africa

- Algeria
- Angola
- Benin
- Botswana

America

- Canada
- Chile
- Mexico
- United States

Asia

- China
- Korea
- India
- Japan

Europe

- Austria
- England
- France
- Germany
- Netherlands
- Switzerland

Oceania

- Australia
- Fiji
- New Zealand
- Samoa

autoSwitch

## Right to Left (RTL)

Some languages render content from the right to the left of the page (Arabic and Hebrew are typical examples) . HTML accommodates this with the 'dir' attribute. Setting 'dir' to 'rtl' on any element causes the element's content to flow from right to left.

The TabPanel supports this automatically. If the element hosting the control has the 'dir' attribute set to 'rtl', the panel will render with tabs aligned from right to left. You don't have to set any properties on the control.

Note that the 'dir' attribute value is inherited, so if you set it on the body tag for example, the entire page will be rendered from right to left, including the TabPanel.

Note also that CSS has a 'direction' attribute that performs the same function as the 'dir' element attribute. The 'dir' attribute is generally considered more appropriate for several reasons, including the fact that it can be used in CSS rules.

HTML
<div id="tabRtl" dir="rtl"> <div> <a>Africa</a> <div> <ul> <li>Algeria</li> <li>Angola</li> <li>Benin</li> <li>Botswana</li> </ul> </div> </div> <div> <a>America</a> <div> <ul> <li>Canada</li> <li>Chile</li> <li>Mexico</li> <li>United States</li> </ul> </div> </div> <div> <a>Asia</a> <div> <ul> <li>China</li> <li>Korea</li> <li>India</li> <li>Japan</li> </ul> </div> </div> <div> <a>Europe</a> <div> <ul> <li>Austria</li> <li>England</li> <li>France</li> <li>Germany</li> <li>Netherlands</li> <li>Switzerland</li> </ul> </div> </div> <div> <a>Oceania</a> <div> <ul> <li>Australia</li> <li>Fiji</li> <li>New Zealand</li> <li>Samoa</li> </ul> </div> </div> </div>
JS
var tabRtl = new wijmo.nav.TabPanel('#tabRtl');

#### Result (live):

Africa

- Algeria
- Angola
- Benin
- Botswana

America

- Canada
- Chile
- Mexico
- United States

Asia

- China
- Korea
- India
- Japan

Europe

- Austria
- England
- France
- Germany
- Netherlands
- Switzerland

Oceania

- Australia
- Fiji
- New Zealand
- Samoa