src/components/tabs/Tabs.js
import _ from 'lodash';
import NestedComponent from '../_classes/nested/NestedComponent';
export default class TabsComponent extends NestedComponent {
static schema(...extend) {
return NestedComponent.schema({
label: 'Tabs',
type: 'tabs',
input: false,
key: 'tabs',
persistent: false,
tableView: false,
components: [
{
label: 'Tab 1',
key: 'tab1',
components: [],
},
],
}, ...extend);
}
static get builderInfo() {
return {
title: 'Tabs',
group: 'layout',
icon: 'folder-o',
weight: 50,
documentation: '/userguide/#tabs',
schema: TabsComponent.schema(),
};
}
get defaultSchema() {
return TabsComponent.schema();
}
get schema() {
const schema = super.schema;
// We need to clone this because the builder uses the "components" reference and this would reset that reference.
const components = _.cloneDeep(this.component.components);
schema.components = components.map((tab, index) => {
tab.components = this.tabs[index].map((component) => component.schema);
return tab;
});
return schema;
}
get tabKey() {
return `tab-${this.key}`;
}
get tabLikey() {
return `tabLi-${this.key}`;
}
get tabLinkKey() {
return `tabLink-${this.key}`;
}
constructor(...args) {
super(...args);
this.currentTab = 0;
this.noField = true;
}
init() {
this.components = [];
this.tabs = [];
_.each(this.component.components, (tab, index) => {
this.tabs[index] = [];
// Initialize empty tabs.
tab.components = tab.components || [];
_.each(tab.components, (comp) => {
const component = this.createComponent(comp);
component.tab = index;
this.tabs[index].push(component);
});
});
}
render() {
return super.render(this.renderTemplate('tab', {
tabKey: this.tabKey,
tabLikey: this.tabLikey,
tabLinkKey: this.tabLinkKey,
currentTab: this.currentTab,
tabComponents: this.tabs.map(tab => this.renderComponents(tab))
}, (this.options.flatten || this.options.pdf ? 'flat' : null)));
}
attach(element) {
this.loadRefs(element, { [this.tabLinkKey]: 'multiple', [this.tabKey]: 'multiple', [this.tabLikey]: 'multiple' });
const superAttach = super.attach(element);
this.refs[this.tabLinkKey].forEach((tabLink, index) => {
this.addEventListener(tabLink, 'click', (event) => {
event.preventDefault();
this.setTab(index);
});
});
this.refs[this.tabKey].forEach((tab, index) => {
this.attachComponents(tab, this.tabs[index], this.component.components[index].components);
});
return superAttach;
}
detach(all) {
super.detach(all);
}
/**
* Set the current tab.
*
* @param index
*/
setTab(index) {
if (
!this.tabs ||
!this.tabs[index] ||
!this.refs[this.tabKey] ||
!this.refs[this.tabKey][index]
) {
return;
}
this.currentTab = index;
_.each(this.refs[this.tabKey], (tab) => {
this.removeClass(tab, 'formio-tab-panel-active');
tab.style.display = 'none';
});
this.addClass(this.refs[this.tabKey][index], 'formio-tab-panel-active');
this.refs[this.tabKey][index].style.display = 'block';
_.each(this.refs[this.tabLinkKey], (tabLink, tabIndex) => {
if (this.refs[this.tabLinkKey][tabIndex]) {
this.removeClass(tabLink, 'formio-tab-link-active');
}
if (this.refs[this.tabLikey][tabIndex]) {
this.removeClass(this.refs[this.tabLikey][tabIndex], 'formio-tab-link-container-active');
}
});
if (this.refs[this.tabLikey][index]) {
this.addClass(this.refs[this.tabLikey][index], 'formio-tab-link-container-active');
}
if (this.refs[this.tabLinkKey][index]) {
this.addClass(this.refs[this.tabLinkKey][index], 'formio-tab-link-active');
}
this.triggerChange();
}
beforeFocus(component) {
if ('beforeFocus' in this.parent) {
this.parent.beforeFocus(this);
}
const tabIndex = this.tabs.findIndex((tab) => {
return tab.some((comp) => comp === component);
});
if (tabIndex !== -1) {
this.setTab(tabIndex);
}
}
}