import {
AfterContentInit,
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ContentChild,
ContentChildren,
EventEmitter,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
Output,
QueryList,
Renderer2,
SimpleChange,
TemplateRef,
ViewChild,
ViewChildren
} from '@angular/core';
import { TabToggleDirective } from './tabs.directive';
import { removeListeners, removeSubscriptions } from '../helpers';
// @TODO Vertical tabs
/*
*
*/
@Component({
selector: 'mk-tab-header',
template: '',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TabHeaderComponent {
@ViewChild('templateRef') public templateRef: TemplateRef;
}
/*
*
*/
@Component({
selector: 'mk-tab-content',
template: '',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TabContentComponent {
@ViewChild('templateRef') public templateRef: TemplateRef;
}
/*
*
*/
@Component({
selector: 'mk-tab',
template: '',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TabComponent implements OnInit {
public index: number;
public isActive = false;
private contentTemplateRef: TemplateRef;
@Input() public header: string;
@Input() public isDisabled: boolean;
@Input() public tabColor: string;
@ViewChild('templateRef') public templateRef: TemplateRef;
@ContentChild(TabHeaderComponent) public tabHeaderComponent: TabHeaderComponent;
@ContentChild(TabContentComponent) public tabContentComponent: TabContentComponent;
/**
* @method ngOnInit
*/
ngOnInit() {
if (this.tabContentComponent) {
this.contentTemplateRef = this.tabContentComponent.templateRef;
} else {
this.contentTemplateRef = this.templateRef;
}
}
}
/*
*
*/
@Component({
selector: 'mk-tabs-header',
template: '',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TabsHeaderComponent {
@ViewChild('templateRef') public templateRef: TemplateRef;
}
/*
*
*/
@Component({
selector: 'mk-tabs',
templateUrl: './tabs.component.html',
styleUrls: ['./tabs.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TabsComponent implements AfterContentInit, AfterViewInit, OnChanges, OnDestroy {
private activatedTabIndex: number;
private listeners = [];
private subscriptions = [];
@Input() public set activeTabIndex(index: number) {
this.activatedTabIndex = index;
this.changeDetectorRef.detectChanges();
}
@Input() public header: string;
@Input() public headerStyleClass = 'header pull-left';
@Input() public navStyleClass = 'nav nav-tabs';
@Input() public contentStyleClass = 'tab-content';
@Input() public styleClass = 'nav-tabs-custom';
@Input() public tabsColor: string;
@Output() public onClose = new EventEmitter();
@Output() public onOpen = new EventEmitter();
@ContentChild(TabsHeaderComponent) public tabsHeaderComponent: TabsHeaderComponent;
@ContentChildren(TabComponent) public tabs: QueryList;
@ViewChildren(TabToggleDirective) public tabToggleDirectives: QueryList;
/**
* @method constructor
* @param changeDetectorRef [description]
* @param ngZone [description]
* @param renderer2 [description]
*/
constructor(
private changeDetectorRef: ChangeDetectorRef,
private ngZone: NgZone,
private renderer2: Renderer2
) {}
/**
* @method ngAfterViewInit
*/
ngAfterContentInit() {
// Set tab index on load.
this.setTabIndex();
// Update tab index if tabs is updated.
this.subscriptions.push(this.tabs.changes.subscribe(() => {
this.setTabIndex();
}));
// Open tab on load.
this.openTabIndex();
}
/**
* @method ngAfterViewInit
*/
ngAfterViewInit() {
// Set tab toggles on load.
this.setTabsToggle();
// Update tab toggles if tabs is updated.
this.subscriptions.push(this.tabToggleDirectives.changes.subscribe(() => {
this.setTabsToggle();
}));
}
/**
* @method ngOnChanges
* @param changes [description]
*/
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
if (changes.activeTabIndex) {
this.openTabIndex();
}
}
/**
* @method ngOnDestroy
*/
ngOnDestroy() {
removeListeners(this.listeners);
removeSubscriptions(this.subscriptions);
}
/**
* [toggleTab description]
* @method toggleTab
*/
public openTabIndex(): void {
if (this.tabs) {
this.tabs.forEach((tab: TabComponent) => {
if (this.activatedTabIndex === tab.index || (this.activatedTabIndex === undefined && tab.index === 0)) {
tab.isActive = true;
this.onOpen.emit({index: tab.index});
this.changeDetectorRef.detectChanges();
} else if (tab.isActive) {
tab.isActive = false;
this.onClose.emit({index: tab.index});
this.changeDetectorRef.detectChanges();
}
});
}
}
/**
* [openTab description]
* @method openTab
* @param event [description]
* @param tabToOpen [description]
*/
public openTab(event: Event, tabToOpen: TabComponent): void {
event.preventDefault();
tabToOpen.isActive = true;
this.onOpen.emit({event, index: tabToOpen.index});
this.tabs.forEach((tab: TabComponent) => {
if (tab.isActive && tabToOpen !== tab) {
tab.isActive = false;
this.onClose.emit({event, index: tab.index});
}
});
}
/**
* [setTabIndex description]
* @method setTabIndex
*/
private setTabIndex(): void {
this.tabs.forEach((tab: TabComponent, index: number) => {
tab.index = index;
});
this.changeDetectorRef.detectChanges();
}
/**
* [setTabsToggle description]
* @method setTabsToggle
*/
private setTabsToggle(): void {
this.listeners = removeListeners(this.listeners);
this.ngZone.runOutsideAngular(() => {
this.tabToggleDirectives.forEach((tabToggle: TabToggleDirective) => {
this.listeners.push(this.renderer2.listen(tabToggle.elementRef.nativeElement, 'click', (event) => {
this.openTab(event, tabToggle.tabComponent);
this.changeDetectorRef.detectChanges();
}));
});
});
}
}