### File

`src/app/test.component.ts`

### Extends

`AbstractJigsawComponent`

### Implements

`AfterViewInit`

### Metadata

selector | `jigsaw-tab`

template

    tab.html

### Index

###### Properties

- Public _$selectedIndex
- Public _$tabPanes
- Private _inkBarStyle
- Private _tabContent
- Private _tabLabel
- Public length

###### Methods

- Public _$tabClick
- Private _asyncSetStyle
- Private _autoSelect
- Private _getLabelOffsetByKey
- Private _getTabPaneByIndex
- Private _handleSelect
- Private _handleSelectChange
- Private _isTabPane
- Private _setInkBarStyle
- Public addTab
- Public hideTab
- ngAfterViewInit
- Public removeTab
- Public showTab

###### Inputs

- selectedIndex

###### Outputs

- selectChange
- selectedIndexChange

###### Accessors

- selectedIndex

### Constructor

`constructor(_cfr: ComponentFactoryResolver, _changeDetector: ChangeDetectorRef, _viewContainer: ViewContainerRef)`
Defined in src/app/test.component.ts:24

Parameters :

Name | Type | Optional
_cfr | `ComponentFactoryResolver` | No
_changeDetector | `ChangeDetectorRef` | No
_viewContainer | `ViewContainerRef` | No

### Inputs

selectedIndex
Type : `number`
Defined in src/app/test.component.ts:64

### Outputs

selectChange
Type : `EventEmitter`
Defined in src/app/test.component.ts:46

selectedIndexChange
Type : `EventEmitter`
Defined in src/app/test.component.ts:80

### Methods

Public _$tabClick
`_$tabClick(index)`
Defined in src/app/test.component.ts:54

tab页点击

Parameters :

Name | Optional
index | No

Returns : `void`

Private _asyncSetStyle
`_asyncSetStyle(index: number)`
Defined in src/app/test.component.ts:128

Parameters :

Name | Type | Optional
index | `number` | No

Returns : `void`

Private _autoSelect
`_autoSelect()`
Defined in src/app/test.component.ts:122
Returns : `void`

Private _getLabelOffsetByKey
`_getLabelOffsetByKey(key: number)`
Defined in src/app/test.component.ts:102

Parameters :

Name | Type | Optional
key | `number` | No

Returns : `any`

Private _getTabPaneByIndex
`_getTabPaneByIndex(key)`
Defined in src/app/test.component.ts:118

Parameters :

Name | Optional
key | No

Returns : `JigsawTabPane`

Private _handleSelect
`_handleSelect()`
Defined in src/app/test.component.ts:248

当 没有指定选择哪个tab时自动处理选中的函数: 使用场景:

1. 隐藏了当前选中的tab-pane
2. 删除了当前的tab-pane 规则: 1. 最后一个非disabled的tabPane
   2. 否则隐藏tab 条.

Returns : `void`

Private _handleSelectChange
`_handleSelectChange(index)`
Defined in src/app/test.component.ts:82

Parameters :

Name | Optional
index | No

Returns : `void`

Private _isTabPane
`_isTabPane(tabPane: any)`
Defined in src/app/test.component.ts:171

Parameters :

Name | Type | Optional
tabPane | `any` | No

Returns : `boolean`

Private _setInkBarStyle
`_setInkBarStyle(index: number)`
Defined in src/app/test.component.ts:91

Parameters :

Name | Type | Optional
index | `number` | No

Returns : `void`

Public addTab
`addTab(title: string | TemplateRef<any> | Type<IDynamicInstantiatable>, content: TemplateRef<any> | Type<IDynamicInstantiatable>, initData?: Object)`
Defined in src/app/test.component.ts:184

添加tab页

Parameters :

Name | Type | Optional
title | `string | TemplateRef<any> | Type<IDynamicInstantiatable>` | No
content | `TemplateRef<any> | Type<IDynamicInstantiatable>` | No
initData | `Object` | Yes

Returns : `void`

Public hideTab
`hideTab(index)`
Defined in src/app/test.component.ts:148

隐藏对应的Tab页.

Parameters :

Name | Optional
index | No

Returns : `void`

ngAfterViewInit
`ngAfterViewInit()`
Defined in src/app/test.component.ts:134
Returns : `void`

Public removeTab
`removeTab(index)`
Defined in src/app/test.component.ts:220

销毁指定的Tab页. 从0开始计数.

Parameters :

Name | Optional
index | No

Returns : `void`

Public showTab
`showTab(index)`
Defined in src/app/test.component.ts:162

显示对应的Tab页, 如果已经是显示的没有变化, 隐藏的显示, 没有打印出警告.

Parameters :

Name | Optional
index | No

Returns : `void`

### Properties

Public _$selectedIndex
Type : `number`
Defined in src/app/test.component.ts:61

Public _$tabPanes
Type : `QueryList<JigsawTabPane>`
Decorators : `@ContentChildren(JigsawTabPane)`
Defined in src/app/test.component.ts:37

Private _inkBarStyle
Type : `object`
Default value : `{}`
Defined in src/app/test.component.ts:89

Private _tabContent
Type : `QueryList<JigsawTabContent>`
Decorators : `@ViewChildren(JigsawTabContent)`
Defined in src/app/test.component.ts:43

Private _tabLabel
Type : `QueryList<JigsawTabLabel>`
Decorators : `@ViewChildren(JigsawTabLabel)`
Defined in src/app/test.component.ts:40

Public length
Type : `number`
Defined in src/app/test.component.ts:48

### Accessors

selectedIndex
get `selectedIndex()`
Defined in src/app/test.component.ts:64
set `selectedIndex(value: number)`
Defined in src/app/test.component.ts:68

Parameters :

Name | Type | Optional
value | `number` | No

Returns : `void`

    import {
        Component,
        ContentChildren,
        QueryList,
        Input,
        ViewChildren,
        AfterViewInit,
        Output,
        EventEmitter,
        TemplateRef,
        ViewContainerRef,
        ComponentFactoryResolver,
        Type,
        ChangeDetectorRef
    } from '@angular/core';
    import { JigsawTabPane } from './tab-pane';
    import { JigsawTabContent, JigsawTabLabel } from './tab-item';
    import { AbstractJigsawComponent, IDynamicInstantiatable } from '../core';

    @Component({
        selector: 'jigsaw-tab',
        template: 'tab.html'
    })
    export class JigsawTab extends AbstractJigsawComponent implements AfterViewInit {
        constructor(
            private _cfr: ComponentFactoryResolver,
            private _changeDetector: ChangeDetectorRef,
            private _viewContainer: ViewContainerRef
        ) {
            super();
        }

        /**
         * @internal
         */
        @ContentChildren(JigsawTabPane)
        public _$tabPanes: QueryList<JigsawTabPane>;

        @ViewChildren(JigsawTabLabel)
        private _tabLabel: QueryList<JigsawTabLabel>;

        @ViewChildren(JigsawTabContent)
        private _tabContent: QueryList<JigsawTabContent>;

        @Output()
        public selectChange = new EventEmitter<JigsawTabPane>();

        public length: number;

        /**
         * tab页点击
         * @internal
         */
        public _$tabClick(index) {
            this.selectedIndex = index;
        }

        /**
         * @internal
         */
        public _$selectedIndex: number;

        @Input()
        public get selectedIndex(): number {
            return this._$selectedIndex;
        }

        public set selectedIndex(value: number) {
            if (this._$selectedIndex !== value && typeof value == 'number') {
                this._$selectedIndex = value;

                if (this.initialized) {
                    this._handleSelectChange(value);
                }
                this._changeDetector.detectChanges();
            }
        }

        @Output()
        public selectedIndexChange = new EventEmitter<number>();

        private _handleSelectChange(index) {
            this.selectChange.emit(this._getTabPaneByIndex(index));
            this.selectedIndexChange.emit(index);

            this._asyncSetStyle(index);
        }

        private _inkBarStyle: object = {};

        private _setInkBarStyle(index: number) {
            let labelPos = this._getLabelOffsetByKey(index);

            this._inkBarStyle = {
                display: 'block',
                transform: 'translate3d(' + labelPos.offSet + 'px, 0px, 0px)',
                width: labelPos.width + 'px'
            };
        }

        // 将有纵向切换的封装.
        private _getLabelOffsetByKey(key: number): any {
            let currentLabel = this._tabLabel.find(item => item.key === key);

            // 非法的 key // 有可能getTop 等扩展Tab页时再重构.
            if (currentLabel) {
                // 找到对应的Label
                return {
                    offSet: currentLabel.getOffsetLeft(),
                    width: currentLabel.getOffsetWidth()
                };
            } else {
                console.warn('没有对应key的tab-Label');
                return {};
            }
        }

        private _getTabPaneByIndex(key): JigsawTabPane {
            return this._$tabPanes.find((item, index) => index === key);
        }

        private _autoSelect() {
            this.selectedIndex = this._$tabPanes
                .toArray()
                .findIndex(tabPane => !tabPane.disabled && !tabPane.hidden);
        }

        private _asyncSetStyle(index: number): void {
            setTimeout(() => {
                this._setInkBarStyle(index);
            }, 0);
        }

        ngAfterViewInit() {
            if (this.selectedIndex != null) {
                this._handleSelectChange(this.selectedIndex);
            } else {
                this._autoSelect();
            }

            this.length = this._$tabPanes.length;
        }

        /**
         * 隐藏对应的Tab页.
         * @param key (tab pane 的顺序.)
         */
        public hideTab(index): void {
            let tabPane = this._getTabPaneByIndex(index);

            if (!this._isTabPane(tabPane)) return;

            tabPane.hidden = true;

            this._handleSelect();
        }

        /**
         * 显示对应的Tab页, 如果已经是显示的没有变化, 隐藏的显示, 没有打印出警告.
         * @param index
         */
        public showTab(index) {
            let tabPane = this._getTabPaneByIndex(index);

            if (!this._isTabPane(tabPane)) return;

            tabPane.hidden = false;
            this.selectedIndex = index;
        }

        private _isTabPane(tabPane: any): boolean {
            if (!tabPane) {
                console.info('没有找到对应的索引的tab-pane');
                return false;
            } else {
                return true;
            }
        }

        /**
         * 添加tab页
         * @param tabPane
         */
        public addTab(
            title: string | TemplateRef<any> | Type<IDynamicInstantiatable>,
            content: TemplateRef<any> | Type<IDynamicInstantiatable>,
            initData?: Object
        ) {
            const factory = this._cfr.resolveComponentFactory(JigsawTabPane);
            let tabPane: JigsawTabPane = this._viewContainer.createComponent(factory).instance;
            if (typeof title == 'string') {
                tabPane.title = title;
            } else {
                tabPane.label = title;
            }
            tabPane.content = content;
            tabPane.initData = initData;

            let tabTemp = this._$tabPanes.toArray();
            tabTemp.push(tabPane);
            this._$tabPanes.reset(tabTemp);
            this.length = this._$tabPanes.length;
            this.selectedIndex = this._$tabPanes.length - 1;

            //router link
            setTimeout(() => {
                let link = this._tabLabel
                    .find(item => item.key === this.selectedIndex)
                    .elementRef.nativeElement.querySelector('[routerLink]');
                if (link) {
                    link.click();
                }
            }, 0);
        }

        /**
         * 销毁指定的Tab页. 从0开始计数.
         * @param index
         */
        public removeTab(index) {
            if (this._$tabPanes.length - index < 1) {
                console.info('没有对应tab-pane 供删除');
                return;
            }

            let tabTemp = this._$tabPanes.toArray();
            tabTemp.splice(index, 1); // 去掉要删除的元素;

            // 重新修改queryList. 不确定这么做有没有什么隐患.
            this._$tabPanes.reset(tabTemp);
            this.length = this._$tabPanes.length;
            if (this.selectedIndex == index) {
                this._handleSelect();
            } else {
                this.selectedIndex = this.selectedIndex - 1;
            }
        }

        /**
         * 当 没有指定选择哪个tab时自动处理选中的函数:
         * 使用场景:
         *  1. 隐藏了当前选中的tab-pane
         *  2. 删除了当前的tab-pane
         *  规则: 1. 最后一个非disabled的tabPane
         *        2. 否则隐藏tab 条.
         * @private
         */
        private _handleSelect() {
            let tabPane = this._getTabPaneByIndex(this.selectedIndex);

            if (!tabPane || tabPane.hidden || tabPane.disabled) {
                this._autoSelect();
            } else {
                this._asyncSetStyle(this.selectedIndex);
            }
        }
    }

Legend
Html element
Component
Html element with directive

# results matching ""

# No results matching ""