• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / igniteui-angular / 28358286454

29 Jun 2026 08:17AM UTC coverage: 90.127% (-0.05%) from 90.174%
28358286454

Pull #17246

github

web-flow
Merge 21687d939 into 07bdcd752
Pull Request #17246: fix(pivot-grid): fix date format based on the localization

14921 of 17392 branches covered (85.79%)

Branch coverage included in aggregate %.

29 of 32 new or added lines in 4 files covered. (90.63%)

735 existing lines in 76 files now uncovered.

29992 of 32441 relevant lines covered (92.45%)

34632.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.62
/projects/igniteui-angular/tabs/src/tabs/tabs/tab-header.component.ts
1
import { AfterViewInit, Component, HostBinding, HostListener, NgZone, OnDestroy, inject, ChangeDetectionStrategy } from '@angular/core';
2
import { IgxTabHeaderDirective } from '../tab-header.directive';
3
import { IgxTabHeaderBase } from '../tabs.base';
4
import { IgxTabsComponent } from './tabs.component';
5
import { getResizeObserver, isLeftToRight } from 'igniteui-angular/core';
6

7
@Component({
8
    selector: 'igx-tab-header',
9
    templateUrl: 'tab-header.component.html',
10
    providers: [{ provide: IgxTabHeaderBase, useExisting: IgxTabHeaderComponent }],
11
    changeDetection: ChangeDetectionStrategy.Eager,
12
    standalone: true
13
})
14
export class IgxTabHeaderComponent extends IgxTabHeaderDirective implements AfterViewInit, OnDestroy {
3✔
15
    protected override tabs = inject(IgxTabsComponent);
220✔
16
    private ngZone = inject(NgZone);
220✔
17

18
    /** @hidden @internal */
19
    @HostBinding('class.igx-tabs__header-item--selected')
20
    public get provideCssClassSelected(): boolean {
21
        return this.tab.selected;
1,564✔
22
    }
23

24
    /** @hidden @internal */
25
    @HostBinding('class.igx-tabs__header-item--disabled')
26
    public get provideCssClassDisabled(): boolean {
27
        return this.tab.disabled;
1,564✔
28
    }
29

30
    /** @hidden @internal */
31
    @HostBinding('class.igx-tabs__header-item')
32
    public cssClass = true;
220✔
33

34
    private _resizeObserver: ResizeObserver;
35

36
    /** @hidden @internal */
37
    @HostListener('keydown', ['$event'])
38
    public keyDown(event: KeyboardEvent) {
39
        let unsupportedKey = false;
57✔
40
        const itemsArray = this.tabs.items.toArray();
57✔
41
        const previousIndex = itemsArray.indexOf(this.tab);
57✔
42
        let newIndex = previousIndex;
57✔
43
        const hasDisabledItems = itemsArray.some((item) => item.disabled);
183✔
44

45
        switch (event.key) {
57!
46
            case this.platform.KEYMAP.ARROW_RIGHT:
47
                newIndex = this.getNewSelectionIndex(newIndex, itemsArray, event.key, hasDisabledItems);
21✔
48
                break;
21✔
49
            case this.platform.KEYMAP.ARROW_LEFT:
50
                newIndex = this.getNewSelectionIndex(newIndex, itemsArray, event.key, hasDisabledItems);
15✔
51
                break;
15✔
52
            case this.platform.KEYMAP.HOME:
53
                event.preventDefault();
7✔
54
                newIndex = 0;
7✔
55
                while (itemsArray[newIndex].disabled && newIndex < itemsArray.length) {
7✔
56
                    newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1;
2!
57
                }
58
                break;
7✔
59
            case this.platform.KEYMAP.END:
60
                event.preventDefault();
5✔
61
                newIndex = itemsArray.length - 1;
5✔
62
                while (hasDisabledItems && itemsArray[newIndex].disabled && newIndex > 0) {
5✔
63
                    newIndex = newIndex === 0 ? itemsArray.length - 1 : newIndex - 1;
1!
64
                }
65
                break;
5✔
66
            case this.platform.KEYMAP.ENTER:
67
            case this.platform.KEYMAP.SPACE:
68
                event.preventDefault();
9✔
69
                if (this.tabs.activation === 'manual') {
9✔
70
                    this.nativeElement.click();
8✔
71
                }
72
                unsupportedKey = true;
9✔
73
                break;
9✔
74
            default:
75
                unsupportedKey = true;
×
UNCOV
76
                break;
×
77
        }
78

79
        if (!unsupportedKey) {
57✔
80
            itemsArray[newIndex].headerComponent.nativeElement.focus({ preventScroll: true });
48✔
81
            if (this.tabs.activation === 'auto') {
48✔
82
                this.tabs.selectedIndex = newIndex;
31✔
83
            }
84
        }
85
    }
86

87
    /** @hidden @internal */
88
    public ngAfterViewInit(): void {
89
        this.ngZone.runOutsideAngular(() => {
220✔
90
            if (this.platform.isBrowser) {
220✔
91
                this._resizeObserver = new (getResizeObserver())(() => {
220✔
92
                    this.tabs.realignSelectedIndicator();
134✔
93
                });
94
                this._resizeObserver.observe(this.nativeElement);
220✔
95
            }
96
        });
97
    }
98

99
    /** @hidden @internal */
100
    public ngOnDestroy(): void {
101
        this.ngZone.runOutsideAngular(() => {
220✔
102
            this._resizeObserver?.disconnect();
220✔
103
        });
104
    }
105

106
    private getNewSelectionIndex(newIndex: number, itemsArray: any[], key: string, hasDisabledItems: boolean): number {
107
        const rtl = !isLeftToRight(this.nativeElement);
36✔
108

109
        if ((key === this.platform.KEYMAP.ARROW_RIGHT && !rtl) || (key === this.platform.KEYMAP.ARROW_LEFT && rtl)) {
36✔
110
            newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1;
22✔
111
            while (hasDisabledItems && itemsArray[newIndex].disabled && newIndex < itemsArray.length) {
22✔
112
                newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1;
4✔
113
            }
114
        } else {
115
            newIndex = newIndex === 0 ? itemsArray.length - 1 : newIndex - 1;
14✔
116
            while (hasDisabledItems && itemsArray[newIndex].disabled && newIndex >= 0) {
14✔
117
                newIndex = newIndex === 0 ? itemsArray.length - 1 : newIndex - 1;
5✔
118
            }
119
        }
120
        return newIndex;
36✔
121
    }
122
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc