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

IgniteUI / igniteui-angular / 16676460874

01 Aug 2025 01:34PM UTC coverage: 91.439% (+0.02%) from 91.424%
16676460874

push

github

web-flow
Merge pull request #16104 from IgniteUI/rivanova/fix-16100-20.0.x

fix(tooltip): prevent adding multiple document touch event listeners - 20.0.x

13458 of 15798 branches covered (85.19%)

2 of 2 new or added lines in 1 file covered. (100.0%)

26 existing lines in 6 files now uncovered.

27172 of 29716 relevant lines covered (91.44%)

34512.13 hits per line

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

97.06
/projects/igniteui-angular/src/lib/grids/headers/grid-header-group.component.ts
1
import {
2
    ChangeDetectionStrategy,
3
    ChangeDetectorRef,
4
    Component,
5
    DoCheck,
6
    ElementRef,
7
    forwardRef,
8
    HostBinding,
9
    HostListener,
10
    Inject,
11
    Input,
12
    QueryList,
13
    ViewChild,
14
    ViewChildren
15
} from '@angular/core';
16
import { IgxFilteringService } from '../filtering/grid-filtering.service';
17
import { IgxColumnResizingService } from '../resizing/resizing.service';
18
import { IgxGridHeaderComponent } from './grid-header.component';
19
import { IgxGridFilteringCellComponent } from '../filtering/base/grid-filtering-cell.component';
20
import { ColumnType, GridType, IGX_GRID_BASE } from '../common/grid.interface';
21
import { GridSelectionMode } from '../common/enums';
22
import { PlatformUtil } from '../../core/utils';
23
import { IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe } from './pipes';
24
import { IgxResizeHandleDirective } from '../resizing/resize-handle.directive';
25
import { IgxIconComponent } from '../../icon/icon.component';
26
import { IgxColumnMovingDropDirective } from '../moving/moving.drop.directive';
27
import { IgxColumnMovingDragDirective } from '../moving/moving.drag.directive';
28
import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
29

30
const Z_INDEX = 9999;
3✔
31

32
/**
33
 * @hidden
34
 */
35
@Component({
36
    changeDetection: ChangeDetectionStrategy.OnPush,
37
    selector: 'igx-grid-header-group',
38
    templateUrl: './grid-header-group.component.html',
39
    imports: [NgClass, NgStyle, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxIconComponent, NgTemplateOutlet, IgxGridHeaderComponent, IgxGridFilteringCellComponent, IgxResizeHandleDirective, IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe]
40
})
41
export class IgxGridHeaderGroupComponent implements DoCheck {
3✔
42

43
    @HostBinding('style.grid-row-end')
44
    public get rowEnd(): number {
45
        return this.column.rowEnd;
242,837✔
46
    }
47

48
    @HostBinding('style.grid-column-end')
49
    public get colEnd(): number {
50
        return this.column.colEnd;
242,837✔
51
    }
52

53
    @HostBinding('style.grid-row-start')
54
    public get rowStart(): number {
55
        return this.column.rowStart;
242,837✔
56
    }
57

58
    @HostBinding('style.grid-column-start')
59
    public get colStart(): number {
60
        return this.column.colStart;
242,837✔
61
    }
62

63
    @HostBinding('attr.id')
64
    public get headerID() {
65
        return `${this.grid.id}_-1_${this.column.level}_${this.column.visibleIndex}`;
226,777✔
66
    }
67

68
    /**
69
     * Gets the column of the header group.
70
     *
71
     * @memberof IgxGridHeaderGroupComponent
72
     */
73
    @Input()
74
    public column: ColumnType;
75

76
    @HostBinding('class.igx-grid-th--active')
77
    public get active() {
78
        const node = this.grid.navigation.activeNode;
226,782✔
79
        return node && !this.column.columnGroup ?
226,782✔
80
            node.row === -1 && node.column === this.column.visibleIndex && node.level === this.column.level : false;
217,426✔
81
    }
82

83
    public get activeGroup() {
84
        const node = this.grid.navigation.activeNode;
13,692✔
85
        return node ? node.row === -1 && node.column === this.column.visibleIndex && node.level === this.column.level : false;
13,692!
86
    }
87

88
    /**
89
     * @hidden
90
     */
91
    @ViewChild(IgxGridHeaderComponent)
92
    public header: IgxGridHeaderComponent;
93

94
    /**
95
     * @hidden
96
     */
97
    @ViewChild(IgxGridFilteringCellComponent)
98
    public filter: IgxGridFilteringCellComponent;
99

100
    /**
101
     * @hidden
102
     */
103
    @ViewChildren(forwardRef(() => IgxGridHeaderGroupComponent), { read: IgxGridHeaderGroupComponent })
6✔
104
    public children: QueryList<IgxGridHeaderGroupComponent>;
105

106
    /**
107
     * Gets the width of the header group.
108
     *
109
     * @memberof IgxGridHeaderGroupComponent
110
     */
111
    public get width() {
112
        return this.grid.getHeaderGroupWidth(this.column);
×
113
    }
114

115
    @HostBinding('class.igx-grid-thead__item')
116
    public defaultCss = true;
22,159✔
117

118
    constructor(private cdr: ChangeDetectorRef,
22,159✔
119
        @Inject(IGX_GRID_BASE) public grid: GridType,
22,159✔
120
        private ref: ElementRef<HTMLElement>,
22,159✔
121
        public colResizingService: IgxColumnResizingService,
22,159✔
122
        public filteringService: IgxFilteringService,
22,159✔
123
        protected platform: PlatformUtil) { }
22,159✔
124

125
    @HostBinding('class.igx-grid-th--pinned')
126
    public get pinnedCss() {
127
        return this.isPinned;
242,837✔
128
    }
129

130
    @HostBinding('class.igx-grid-th--pinned-last')
131
    public get pinnedLastCss() {
132
        return this.isLastPinned;
242,837✔
133
    }
134

135
    @HostBinding('class.igx-grid-th--pinned-first')
136
    public get pinnedFirstCSS() {
137
        return this.isFirstPinned;
242,837✔
138
    }
139

140
    @HostBinding('class.igx-grid__drag-col-header')
141
    public get headerDragCss() {
142
        return this.isHeaderDragged;
242,837✔
143
    }
144

145
    @HostBinding('class.igx-grid-th--filtering')
146
    public get filteringCss() {
147
        return this.isFiltered;
242,837✔
148
    }
149

150
    /**
151
     * @hidden
152
     */
153
    @HostBinding('style.z-index')
154
    public get zIndex() {
155
        if (!this.column.pinned) {
242,840✔
156
            return null;
238,136✔
157
        }
158
        return Z_INDEX - this.grid.pinnedColumns.indexOf(this.column);
4,704✔
159
    }
160

161
    /**
162
     * @hidden
163
     */
164
    public get ariaHidden(): boolean {
165
        return this.grid.hasColumnGroups && (this.column.hidden || this.grid.navigation.activeNode.row !== -1);
223,755✔
166
    }
167

168
    /**
169
     * Gets whether the header group belongs to a column that is filtered.
170
     *
171
     * @memberof IgxGridHeaderGroupComponent
172
     */
173
    public get isFiltered(): boolean {
174
        return this.filteringService.filteredColumn === this.column;
242,848✔
175
    }
176

177
    /**
178
     * Gets whether the header group is stored in the last column in the pinned area.
179
     *
180
     * @memberof IgxGridHeaderGroupComponent
181
     */
182
    public get isLastPinned(): boolean {
183
        return !this.grid.hasColumnLayouts ? this.column.isLastPinned : false;
242,837✔
184
    }
185

186
    /**
187
     * Gets whether the header group is stored in the first column of the right pinned area.
188
     */
189
    public get isFirstPinned(): boolean {
190
        return !this.grid.hasColumnLayouts ? this.column.isFirstPinned : false;
242,837✔
191
    }
192

193
    @HostBinding('style.display')
194
    public get groupDisplayStyle(): string {
195
        return this.grid.hasColumnLayouts && this.column.children ? 'flex' : '';
242,837✔
196
    }
197

198
    /**
199
     * Gets whether the header group is stored in a pinned column.
200
     *
201
     * @memberof IgxGridHeaderGroupComponent
202
     */
203
    public get isPinned(): boolean {
204
        return this.column.pinned;
242,850✔
205
    }
206

207
    /**
208
     * Gets whether the header group belongs to a column that is moved.
209
     *
210
     * @memberof IgxGridHeaderGroupComponent
211
     */
212
    public get isHeaderDragged(): boolean {
213
        return this.grid.columnInDrag === this.column;
242,837✔
214
    }
215

216
    /**
217
     * @hidden
218
     */
219
    public get hasLastPinnedChildColumn(): boolean {
220
        return this.column.allChildren.some(child => child.isLastPinned);
59,272✔
221
    }
222

223
    /**
224
     * @hidden
225
     */
226
    public get hasFirstPinnedChildColumn(): boolean {
227
        return this.column.allChildren.some(child => child.isFirstPinned);
56,282✔
228
    }
229

230
    /**
231
     * @hidden
232
     */
233
    public get selectable() {
234
        const selectableChildren = this.column.allChildren.filter(c => !c.hidden && c.selectable && !c.columnGroup);
45,435✔
235
        return this.grid.columnSelection !== GridSelectionMode.none &&
13,692✔
236
            this.column.applySelectableClass
237
            && !this.selected && selectableChildren.length > 0
238
            && !this.grid.filteringService.isFilterRowVisible;
239
    }
240

241
    /**
242
     * @hidden
243
     */
244
    public get selected() {
245
        return this.column.selected;
13,708✔
246
    }
247

248
    /**
249
     * @hidden
250
     */
251
    public get height() {
252
        return this.nativeElement.getBoundingClientRect().height;
12✔
253
    }
254

255
    /**
256
     * @hidden
257
     */
258
    public get title() {
259
        return this.column.title || this.column.header;
13,500✔
260
    }
261

262
    public get nativeElement() {
263
        return this.ref.nativeElement;
8,244✔
264
    }
265

266
    /**
267
     * @hidden
268
     */
269
    @HostListener('mousedown', ['$event'])
270
    public onMouseDown(event: MouseEvent): void {
271
        if (!this.grid.allowFiltering ||
51✔
272
            (event.composedPath().findIndex(el =>
273
                (el as Element).tagName?.toLowerCase() === 'igx-grid-filtering-cell') < 1)) {
116✔
274
                // Hack for preventing text selection in IE and Edge while dragging the resize element
275
                event.preventDefault();
50✔
276
        }
277
    }
278

279
    /**
280
     * @hidden
281
     */
282
    public groupClicked(event: MouseEvent): void {
283
        const columnsToSelect = this.column.allChildren.filter(c => !c.hidden && c.selectable && !c.columnGroup).map(c => c.field);
78✔
284
        if (this.grid.columnSelection !== GridSelectionMode.none
18✔
285
            && columnsToSelect.length > 0 && !this.grid.filteringService.isFilterRowVisible) {
286
            const clearSelection = this.grid.columnSelection === GridSelectionMode.single || !event.ctrlKey;
13✔
287
            const rangeSelection = this.grid.columnSelection === GridSelectionMode.multiple && event.shiftKey;
13✔
288
            if (!this.selected) {
13✔
289
                this.grid.selectionService.selectColumns(columnsToSelect, clearSelection, rangeSelection, event);
10✔
290
            } else {
291
                const selectedFields = this.grid.selectionService.getSelectedColumns();
3✔
292
                if ((selectedFields.length === columnsToSelect.length) && selectedFields.every(el => columnsToSelect.includes(el))
3✔
293
                    || !clearSelection) {
294
                    this.grid.selectionService.deselectColumns(columnsToSelect, event);
2✔
295
                } else {
296
                    this.grid.selectionService.selectColumns(columnsToSelect, clearSelection, rangeSelection, event);
1✔
297
                }
298
            }
299
        }
300
    }
301

302
    /**
303
     * @hidden @internal
304
     */
305
    public onPointerDownIndicator(event) {
306
        // Stop propagation of pointer events to now allow column dragging using the header indicators.
UNCOV
307
        event.stopPropagation();
×
308
    }
309

310
    /**
311
     * @hidden @internal
312
     */
313
    public toggleExpandState(event: MouseEvent): void {
314
        event.stopPropagation();
7✔
315
        this.column.expanded = !this.column.expanded;
7✔
316
    }
317

318
    /**
319
     * @hidden @internal
320
     */
321
    public pointerdown(event: PointerEvent): void {
322
        event.stopPropagation();
14✔
323
        this.activate();
14✔
324
        this.grid.theadRow.nativeElement.focus();
14✔
325
    }
326

327
    /*
328
     * This method is necessary due to some specifics related with implementation of column moving
329
     * @hidden
330
     */
331
    public activate() {
332
        this.grid.navigation.setActiveNode(this.activeNode);
94✔
333
        this.grid.theadRow.nativeElement.focus();
94✔
334
    }
335

336
    public ngDoCheck() {
337
        this.cdr.markForCheck();
242,837✔
338
    }
339
    /**
340
     * @hidden
341
     */
342
    public onPinterEnter() {
343
        this.column.applySelectableClass = true;
3✔
344
    }
345

346
    /**
347
     * @hidden
348
     */
349
    public onPointerLeave() {
350
        this.column.applySelectableClass = false;
3✔
351
    }
352

353
    protected get activeNode() {
354
        return {
94✔
355
            row: -1, column: this.column.visibleIndex, level: this.column.level,
356
            mchCache: { level: this.column.level, visibleIndex: this.column.visibleIndex },
357
            layout: this.column.columnLayoutChild ? {
94✔
358
                rowStart: this.column.rowStart,
359
                colStart: this.column.colStart,
360
                rowEnd: this.column.rowEnd,
361
                colEnd: this.column.colEnd,
362
                columnVisibleIndex: this.column.visibleIndex
363
            } : null
364
        };
365
    }
366
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc