TabPanel
A tab panel widget which displays a collection of tabs, each of which can contain other widgets or HTML/text. This widget has a tab bar on top of its contents, and each Tab can be customized using the tab config.
const tabPanel = new TabPanel({
items: {
firstTab : {
title: 'First',
items: {
name : { type: 'textfield', label: 'Name' },
...
}
},
settingsTab : {
title: 'Settings',
tab : {
// Show an icon in the tab
icon : 'fa fa-cog'
},
items: {
...
}
}
}
});
The tab selector buttons are focusable elements. Enter or Space activates a tab, and moves
focus into the newly visible tab item.
//<code-header>
fiddle.title = 'Tab panel';
//</code-header>
new SlideToggle({
insertFirst : targetElement,
label : 'Closable tabs',
checked : true,
onChange({ value }) {
tabPanel.tabBar.items.forEach(tab => tab.closable = value);
}
});
const tabPanel = new TabPanel({
appendTo : targetElement,
height : '25em',
tabBar : {
defaults : {
closable : true
}
},
items : {
main : {
title : 'Tab with widgets',
tab : {
icon : 'fa fa-puzzle-piece'
},
items : {
forename : { type : 'text', label : 'First name', style : 'margin: 2em 1em', required : true },
surname : { type : 'text', label : 'Last name', style : 'margin: 2em 1em' }
}
},
secondary : {
title : 'Tab with basic HTML',
tab : {
icon : 'fa fa-code'
},
items : {
infoWidget : {
type : 'widget',
style : 'padding: 1em',
html : 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
}
}
},
tertiary : {
title : 'Images',
style : 'gap: 3em; padding: 4em; display: grid; grid-template-columns: repeat(3, 1fr)',
tab : {
icon : 'fa fa-image'
},
defaults : {
flex : 1,
type : 'widget',
tag : 'img',
style : 'width: 186px; height: 140px'
},
items : {
gantt : {
elementAttributes : {
src : 'data/Core/images/thumb/gantt.png'
}
},
calendar : {
elementAttributes : {
src : 'data/Core/images/thumb/calendar.png'
}
},
taskboard : {
elementAttributes : {
src : 'data/Core/images/thumb/taskboard.png'
}
}
}
}
}
});Adding non tab items to the tab bar
The TabBar is a subclass of the Toolbar, meaning you can add additional widgets to it. You can add either tab-specific items only shown for the active tab, or you can add static extra items that are shown for all tabs.
Demo showing tab-specific extra items using tabBarItems.
//<code-header>
fiddle.title = 'Tab panel with grid';
//</code-header>
new TabPanel({
appendTo : targetElement,
height : '25em',
onRequirementSearchFieldChange({ value }) {
this.activeItem.store.filter('name', value);
},
onAddWorkOrder() {
this.activeItem.store.add({ workOrderName : 'New work order' });
},
onRequirementsReload() {
this.activeItem.mask('Fake reload...');
this.setTimeout(() => this.activeItem.unmask(), 2000);
},
items : {
main : {
type : 'grid',
title : 'Open Requirements',
features : {
sort : 'name',
stripe : true
},
tabBarItems : [
{
type : 'textfield',
placeholder : 'Search',
field : 'name',
clearable : true,
height : '2.5em',
onChange : 'up.onRequirementSearchFieldChange',
keyStrokeChangeDelay : 300
},
{
type : 'button',
cls : 'b-transparent',
icon : 'fa fa-rotate',
onClick : 'up.onRequirementsReload'
}
],
columns : [
{
text : 'Name',
field : 'name',
width : 200
},
{
type : 'date',
text : 'From Date',
field : 'fromDate',
width : 120
},
{
type : 'date',
text : 'To Date',
field : 'toDate',
width : 120
},
{
text : 'Priority',
field : 'priority',
width : 100,
htmlEncode : false,
renderer : ({ value }) => {
return `<span style="background: ${value === 'Critical' ? 'red' : 'green'};width:10px;height:10px;border-radius: 50%;margin-inline-end:.5em"></span>${value}`;
}
},
{
text : 'Duration',
field : 'duration',
width : 100
},
{
text : 'Proposed Duration',
field : 'proposedDuration',
width : 150
},
{
text : 'Fulfilled Duration',
field : 'fulfilledDuration',
width : 150
},
{
text : 'Remaining Duration',
field : 'remainingDuration',
width : 150
},
{
text : 'Territory',
field : 'territory',
width : 150
},
{
text : 'Time From Promised',
field : 'timeFromPromised',
width : 150
},
{
text : 'Time To Promised',
field : 'timeToPromised',
width : 150
}
],
store : {
fields : [
{ name : 'fromDate', type : 'date' },
{ name : 'toDate', type : 'date' },
{ name : 'duration' },
{ name : 'proposedDuration' },
{ name : 'fulfilledDuration' },
{ name : 'remainingDuration' },
{ name : 'priority' },
{ name : 'territory' },
{ name : 'timeFromPromised' },
{ name : 'timeToPromised' }
],
data : [
{
id : 1,
name : 'TAB1 - Cable Burial',
fromDate : '2024-09-12 10:00',
toDate : '2024-09-12 10:30',
duration : '30 mins',
proposedDuration : '0 mins',
fulfilledDuration : '0 mins',
remainingDuration : '30 mins',
priority : 'Critical',
territory : 'Borders East',
timeFromPromised : '5 mins',
timeToPromised : '0 mins'
},
{
id : 2,
name : 'SUB2 - Subsea cable',
fromDate : '2024-09-12 09:00',
toDate : '2024-09-12 10:00',
duration : '1 hr',
proposedDuration : '0 mins',
fulfilledDuration : '0 mins',
remainingDuration : '1 hr',
priority : 'Critical',
territory : 'Bedfordshire',
timeFromPromised : '0 mins',
timeToPromised : '15 mins'
},
{
id : 3,
name : 'TOW43 - Cell Tower',
fromDate : '2024-09-12 08:15',
toDate : '2024-09-12 09:00',
duration : '45 mins',
proposedDuration : '0 mins',
fulfilledDuration : '0 mins',
remainingDuration : '45 mins',
priority : 'Low',
territory : 'Berkshire West',
timeFromPromised : '10 mins',
timeToPromised : '5 mins'
}
]
}
},
secondary : {
type : 'grid',
title : 'Unscheduled Work Orders',
features : {
sort : 'workOrderName',
stripe : true
},
tabBarItems : [
{
type : 'button',
text : 'Add work order',
onClick : 'up.onAddWorkOrder'
}
],
columns : [
{
text : 'Work Order Name',
field : 'workOrderName',
width : 200
},
{
text : 'Job Type',
field : 'jobType',
width : 150
},
{
text : 'Assigned Crew',
field : 'assignedCrew',
width : 150
},
{
text : 'Estimated Duration',
field : 'estimatedDuration',
width : 150
},
{
text : 'Priority',
field : 'priority',
width : 100
},
{
text : 'Location',
field : 'location',
width : 200
},
{
text : 'Status',
field : 'status',
width : 120
}
],
store : {
fields : [
{ name : 'workOrderName' },
{ name : 'jobType' },
{ name : 'assignedCrew' },
{ name : 'estimatedDuration' },
{ name : 'priority' },
{ name : 'location' },
{ name : 'status' }
],
data : [
{
id : 1,
workOrderName : 'WO123 - Underground Cabling',
jobType : 'Cable Installation',
assignedCrew : 'Crew A',
estimatedDuration : '3 hours',
priority : 'Critical',
location : 'Borders East',
status : 'Pending'
},
{
id : 2,
workOrderName : 'WO124 - Fiber Optic Laying',
jobType : 'Fiber Optic',
assignedCrew : 'Crew B',
estimatedDuration : '2 hours',
priority : 'Low',
location : 'Bedfordshire',
status : 'Pending'
},
{
id : 3,
workOrderName : 'WO125 - Electrical Wiring',
jobType : 'Electrical Work',
assignedCrew : 'Crew C',
estimatedDuration : '1.5 hours',
priority : 'Critical',
location : 'Berkshire West',
status : 'Scheduled'
}
]
}
}
}
});Demo showing static extra items using items
//<code-header>
fiddle.title = 'Extra tab items';
//</code-header>
new TabPanel({
appendTo : targetElement,
height : '25em',
onAddTabClick() {
this.add({
type : 'panel',
title : 'New tab',
items : {
button : {
type : 'button',
text : 'Click me',
onClick() {
Toast.show('Awesome!');
}
}
}
});
},
tabBar : {
items : {
addButton : {
type : 'button',
text : 'Add tab',
onClick : 'up.onAddTabClick'
}
}
},
items : {
main : {
type : 'grid',
title : 'Open Requirements',
features : {
sort : 'name',
stripe : true
},
columns : [
{
text : 'Name',
field : 'name',
width : 200
},
{
type : 'date',
text : 'From Date',
field : 'fromDate',
width : 120
}
],
store : {
fields : [
{ name : 'name' },
{ name : 'fromDate', type : 'date' }
],
data : [
{
id : 1,
name : 'TAB1 - Cable Burial',
fromDate : '2024-09-12 10:00'
}
]
}
},
secondary : {
type : 'grid',
title : 'Unscheduled Work Orders',
features : {
sort : 'workOrderName',
stripe : true
},
columns : [
{
text : 'Work Order Name',
field : 'workOrderName',
width : 200
},
{
text : 'Job Type',
field : 'jobType',
width : 150
},
{
text : 'Assigned Crew',
field : 'assignedCrew',
width : 150
}
],
store : {
fields : [
{ name : 'workOrderName' },
{ name : 'jobType' },
{ name : 'assignedCrew' },
{ name : 'estimatedDuration' },
{ name : 'priority' },
{ name : 'location' },
{ name : 'status' }
],
data : [
{
id : 1,
workOrderName : 'WO123 - Underground Cabling',
jobType : 'Cable Installation',
assignedCrew : 'Crew A',
estimatedDuration : '3 hours',
priority : 'Critical',
location : 'Borders East',
status : 'Pending'
}
]
}
}
}
});Tabs can be drag-dropped
You can easily let users reorder the tabs by setting enableReordering to true.
//<code-header>
fiddle.title = 'Draggable tabs';
//</code-header>
new TabPanel({
appendTo : targetElement,
height : '25em',
tabBar : {
enableReordering : true
},
items : {
main : {
title : 'Tab with widgets',
tab : {
icon : 'fa fa-puzzle-piece'
},
items : {
forename : { type : 'text', label : 'First name', style : 'margin: 2em 1em' },
surname : { type : 'text', label : 'Last name', style : 'margin: 2em 1em' }
}
},
secondary : {
title : 'Tab with basic HTML',
tab : {
icon : 'fa fa-code'
},
items : {
infoWidget : {
type : 'widget',
style : 'padding: 1em',
html : 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'
}
}
},
tertiary : {
title : 'Images',
style : 'gap: 3em; padding: 4em; display: grid; grid-template-columns: repeat(3, 1fr)',
tab : {
icon : 'fa fa-image'
},
defaults : {
flex : 1,
type : 'widget',
tag : 'img',
style : 'width: 186px; height: 140px'
},
items : {
gantt : {
elementAttributes : {
src : 'data/Core/images/thumb/gantt.png'
}
},
calendar : {
elementAttributes : {
src : 'data/Core/images/thumb/calendar.png'
}
},
taskboard : {
elementAttributes : {
src : 'data/Core/images/thumb/taskboard.png'
}
}
}
}
}
});Configs
114
Configs
114Common
Other
The index of the initially active tab.
Specifies whether to slide tabs in and out of visibility.
Set the height of all tabs to match the tab with the highest content.
Additional configuration for the tab bar.
Use this to add more non-tab items to the bar:
new TabPanel({
tabBar : {
items : {
spacer : '->', // Spacer which moves next item to the right
button : { type : 'button', text : 'MyButton' }
}
}
});
Max width of a tab title. 0 means no maximum width. This is default.
Min width of a tab title. 0 means no minimum width. This is default.
Content
CSS
DOM
Float & align
Layout
misc
Misc
Scrolling
Properties
97
Properties
97Class hierarchy
Other
The active tab index. Setting must be done through activeTab
The active child widget. Setting must be done through activeTab
The index of the initially active tab.
CSS
DOM
Layout
Misc
State
Widget hierarchy
Functions
74
Functions
74Configuration
Events
Misc
Other
Widget hierarchy
Events
23
Events
23The active tab is about to be changed. Return false to prevent this.
// Adding a listener using the "on" method
tabPanel.on('beforeTabChange', ({ activeIndex, activeItem, prevActiveIndex, prevActiveItem }) => {
});| Parameter | Type | Description |
|---|---|---|
activeIndex | Number | The new active index. |
activeItem | Widget | The new active child widget. |
prevActiveIndex | Number | The previous active index. |
prevActiveItem | Widget | The previous active child widget. |
The active tab has changed.
// Adding a listener using the "on" method
tabPanel.on('tabChange', ({ activeIndex, activeItem, prevActiveIndex, prevActiveItem }) => {
});| Parameter | Type | Description |
|---|---|---|
activeIndex | Number | The new active index. |
activeItem | Widget | The new active child widget. |
prevActiveIndex | Number | The previous active index. |
prevActiveItem | Widget | The previous active child widget. |
Event handlers
23
Event handlers
23The active tab is about to be changed. Return false to prevent this.
new TabPanel({
onBeforeTabChange({ activeIndex, activeItem, prevActiveIndex, prevActiveItem }) {
}
});| Parameter | Type | Description |
|---|---|---|
activeIndex | Number | The new active index. |
activeItem | Widget | The new active child widget. |
prevActiveIndex | Number | The previous active index. |
prevActiveItem | Widget | The previous active child widget. |
The active tab has changed.
new TabPanel({
onTabChange({ activeIndex, activeItem, prevActiveIndex, prevActiveItem }) {
}
});| Parameter | Type | Description |
|---|---|---|
activeIndex | Number | The new active index. |
activeItem | Widget | The new active child widget. |
prevActiveIndex | Number | The previous active index. |
prevActiveItem | Widget | The previous active child widget. |