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

IgniteUI / igniteui-angular / 20960087204

13 Jan 2026 02:19PM UTC coverage: 12.713% (-78.8%) from 91.5%
20960087204

Pull #16746

github

web-flow
Merge 9afce6e5d into a967f087e
Pull Request #16746: fix(csv): export summaries - master

1008 of 16803 branches covered (6.0%)

19 of 23 new or added lines in 2 files covered. (82.61%)

24693 existing lines in 336 files now uncovered.

3985 of 31345 relevant lines covered (12.71%)

2.49 hits per line

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

45.0
/projects/igniteui-angular/grids/core/src/headers/grid-header.component.ts
1
import {
2
    ChangeDetectionStrategy,
3
    ChangeDetectorRef,
4
    Component,
5
    DoCheck,
6
    ElementRef,
7
    HostBinding,
8
    HostListener,
9
    inject,
10
    Input,
11
    OnDestroy,
12
    TemplateRef,
13
    ViewChild
14
} from '@angular/core';
15
import { IgxColumnResizingService } from '../resizing/resizing.service';
16
import { Subject } from 'rxjs';
17
import { GridType, IGX_GRID_BASE } from '../common/grid.interface';
18
import { GridSelectionMode } from '../common/enums';
19
import { SortingIndexPipe } from './pipes';
20
import { NgTemplateOutlet, NgClass } from '@angular/common';
21
import { IgxIconComponent } from 'igniteui-angular/icon';
22
import { ColumnType, ExpressionsTreeUtil, GridColumnDataType, SortingDirection } from 'igniteui-angular/core';
23

24
/**
25
 * @hidden
26
 */
27
@Component({
28
    changeDetection: ChangeDetectionStrategy.OnPush,
29
    selector: 'igx-grid-header',
30
    templateUrl: 'grid-header.component.html',
31
    imports: [IgxIconComponent, NgTemplateOutlet, NgClass, SortingIndexPipe]
32
})
33
export class IgxGridHeaderComponent implements DoCheck, OnDestroy {
3✔
34
    public grid = inject<GridType>(IGX_GRID_BASE);
3✔
35
    public colResizingService = inject(IgxColumnResizingService);
3✔
36
    public cdr = inject(ChangeDetectorRef);
3✔
37
    private ref = inject<ElementRef<HTMLElement>>(ElementRef);
3✔
38

39
    @Input()
40
    public column: ColumnType;
41

42
    /**
43
     * @hidden
44
     */
45
    @ViewChild('defaultESFHeaderIconTemplate', { read: TemplateRef, static: true })
46
    protected defaultESFHeaderIconTemplate: TemplateRef<any>;
47

48
    /**
49
     * @hidden
50
     */
51
    @ViewChild('defaultSortHeaderIconTemplate', { read: TemplateRef, static: true })
52
    protected defaultSortHeaderIconTemplate;
53

54
    /**
55
     * @hidden
56
     */
57
    @ViewChild('sortIconContainer', { read: ElementRef })
58
    protected sortIconContainer: ElementRef;
59

60
    @HostBinding('class.igx-grid-th--pinned')
61
    public get pinnedCss() {
62
        return this.isPinned;
15✔
63
    }
64

65
    @HostBinding('class.igx-grid-th--pinned-last')
66
    public get pinnedLastCss() {
67
        return this.isLastPinned;
15✔
68
    }
69

70
    @HostBinding('class.igx-grid-th--pinned-first')
71
    public get pinnedFirstCSS() {
72
        return this.isFirstPinned;
15✔
73
    }
74

75
    /**
76
     * Gets whether the header group is stored in the last column in the pinned area.
77
     */
78
    public get isLastPinned(): boolean {
79
        return !this.grid.hasColumnLayouts ? this.column.isLastPinned : false;
15!
80
    }
81

82
    /**
83
     * Gets whether the header group is stored in the first column of the right pinned area.
84
     */
85
    public get isFirstPinned(): boolean {
86
        return !this.grid.hasColumnLayouts ? this.column.isFirstPinned : false;
15!
87
    }
88

89
    /**
90
     * Gets whether the header group is stored in a pinned column.
91
     *
92
     * @memberof IgxGridHeaderGroupComponent
93
     */
94
    public get isPinned(): boolean {
95
        return this.column.pinned;
15✔
96
    }
97
    /**
98
     * @hidden
99
     */
100
    @Input()
101
    @HostBinding('attr.id')
102
    public id: string;
103

104
    /**
105
     * Returns the `aria-selected` of the header.
106
     */
107
    @HostBinding('attr.aria-selected')
108
    public get ariaSelected(): boolean {
109
        return this.column.selected;
15✔
110
    }
111

112
    /**
113
     * Returns the `aria-sort` of the header.
114
     */
115
    @HostBinding('attr.aria-sort')
116
    public get ariaSort() {
117
        return this.sortDirection === SortingDirection.Asc ? 'ascending'
15!
118
            : this.sortDirection === SortingDirection.Desc ? 'descending' : null;
15!
119
    }
120

121
    /**
122
     * @hidden
123
     */
124
    @HostBinding('attr.aria-colindex')
125
    public get ariaColIndx() {
126
        return this.column.index + 1;
15✔
127
    }
128

129
    /**
130
     * @hidden
131
     */
132
    @HostBinding('attr.aria-rowindex')
133
    public get ariaRowIndx() {
134
        return 1;
15✔
135
    }
136

137
    @HostBinding('class.igx-grid-th')
138
    public get columnGroupStyle() {
139
        return !this.column.columnGroup;
15✔
140
    }
141

142
    @HostBinding('class.asc')
143
    public get sortAscendingStyle() {
144
        return this.sortDirection === SortingDirection.Asc;
15✔
145
    }
146

147
    @HostBinding('class.desc')
148
    public get sortDescendingStyle() {
149
        return this.sortDirection === SortingDirection.Desc;
15✔
150
    }
151

152
    @HostBinding('class.igx-grid-th--number')
153
    public get numberStyle() {
154
        return this.column.dataType === GridColumnDataType.Number;
15✔
155
    }
156

157
    @HostBinding('class.igx-grid-th--sortable')
158
    public get sortableStyle() {
159
        return this.column.sortable;
15✔
160
    }
161

162
    @HostBinding('class.igx-grid-th--selectable')
163
    public get selectableStyle() {
164
        return this.selectable;
15✔
165
    }
166

167
    @HostBinding('class.igx-grid-th--filtrable')
168
    public get filterableStyle() {
169
        return this.column.filterable && this.grid.filteringService.isFilterRowVisible;
15✔
170
    }
171

172
    @HostBinding('class.igx-grid-th--sorted')
173
    public get sortedStyle() {
174
        return this.sorted;
15✔
175
    }
176

177
    @HostBinding('class.igx-grid-th--selected')
178
    public get selectedStyle() {
179
        return this.selected;
15✔
180
    }
181

182
    /**
183
     * @hidden
184
     */
185
    public get esfIconTemplate() {
UNCOV
186
        return this.grid.excelStyleHeaderIconTemplate || this.defaultESFHeaderIconTemplate;
×
187
    }
188

189
    /**
190
     * @hidden
191
     */
192
    public get sortIconTemplate() {
UNCOV
193
        if (this.sortDirection === SortingDirection.None && this.grid.sortHeaderIconTemplate) {
×
UNCOV
194
            return this.grid.sortHeaderIconTemplate;
×
UNCOV
195
        } else if (this.sortDirection === SortingDirection.Asc && this.grid.sortAscendingHeaderIconTemplate) {
×
UNCOV
196
            return this.grid.sortAscendingHeaderIconTemplate;
×
UNCOV
197
        } else if (this.sortDirection === SortingDirection.Desc && this.grid.sortDescendingHeaderIconTemplate) {
×
UNCOV
198
            return this.grid.sortDescendingHeaderIconTemplate;
×
199
        } else {
UNCOV
200
            return this.defaultSortHeaderIconTemplate;
×
201
        }
202
    }
203
    /**
204
     * @hidden
205
     */
206
    public get disabled() {
UNCOV
207
        const groupArea = this.grid.groupArea || this.grid.treeGroupArea;
×
UNCOV
208
        if (groupArea?.expressions && groupArea.expressions.length && groupArea.expressions.map(g => g.fieldName).includes(this.column.field)) {
×
UNCOV
209
            return true;
×
210
        }
UNCOV
211
        return false;
×
212
    }
213

214
    public get sorted() {
215
        return this.sortDirection !== SortingDirection.None;
15✔
216
    }
217

218
    public get filterIconClassName() {
UNCOV
219
        return this.column.filteringExpressionsTree || this.isAdvancedFilterApplied() ? 'igx-excel-filter__icon--filtered' : 'igx-excel-filter__icon';
×
220
    }
221

222
    public get selectable() {
223
        return this.grid.columnSelection !== GridSelectionMode.none &&
15!
224
            this.column.applySelectableClass &&
225
            !this.column.selected &&
226
            !this.grid.filteringService.isFilterRowVisible;
227
    }
228

229
    public get selected() {
230
        return this.column.selected
15!
231
            && (!this.grid.filteringService.isFilterRowVisible || this.grid.filteringService.filteredColumn !== this.column);
232
    }
233

234
    public get title() {
235
        return this.column.title || this.column.header || this.column.field;
15✔
236
    }
237

238
    public get nativeElement() {
UNCOV
239
        return this.ref.nativeElement;
×
240
    }
241

242
    public sortDirection = SortingDirection.None;
3✔
243
    protected _destroy$ = new Subject<boolean>();
3✔
244

245
    @HostListener('click', ['$event'])
246
    public onClick(event: MouseEvent) {
UNCOV
247
        if (!this.colResizingService.isColumnResizing) {
×
248

UNCOV
249
            if (this.grid.filteringService.isFilterRowVisible) {
×
UNCOV
250
                if (this.column.filterCellTemplate) {
×
UNCOV
251
                    this.grid.filteringRow.close();
×
UNCOV
252
                    return;
×
253
                }
254

UNCOV
255
                if (this.column.filterable && !this.column.columnGroup &&
×
256
                    !this.grid.filteringService.isFilterComplex(this.column.field)) {
UNCOV
257
                    this.grid.filteringService.filteredColumn = this.column;
×
258
                }
UNCOV
259
            } else if (this.grid.columnSelection !== GridSelectionMode.none && this.column.selectable) {
×
UNCOV
260
                const clearSelection = this.grid.columnSelection === GridSelectionMode.single || !event.ctrlKey;
×
UNCOV
261
                const rangeSelection = this.grid.columnSelection === GridSelectionMode.multiple && event.shiftKey;
×
262

UNCOV
263
                if (!this.column.selected || (this.grid.selectionService.getSelectedColumns().length > 1 && clearSelection)) {
×
UNCOV
264
                    this.grid.selectionService.selectColumn(this.column.field, clearSelection, rangeSelection, event);
×
265
                } else {
UNCOV
266
                    this.grid.selectionService.deselectColumn(this.column.field, event);
×
267
                }
268
            }
269
        }
UNCOV
270
        this.grid.theadRow.nativeElement.focus();
×
271
    }
272

273
    /**
274
     * @hidden
275
     */
276
    @HostListener('pointerenter')
277
    public onPinterEnter() {
UNCOV
278
        this.column.applySelectableClass = true;
×
279
    }
280

281
    /**
282
     * @hidden
283
     */
284
    @HostListener('pointerleave')
285
    public onPointerLeave() {
UNCOV
286
        this.column.applySelectableClass = false;
×
287
    }
288

289
    /**
290
     * @hidden @internal
291
     */
292
    public ngDoCheck() {
293
        this.getSortDirection();
15✔
294
        this.cdr.markForCheck();
15✔
295
    }
296

297
    /**
298
     * @hidden @internal
299
     */
300
    public ngOnDestroy(): void {
301
        this._destroy$.next(true);
3✔
302
        this._destroy$.complete();
3✔
303
    }
304

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

313
    /**
314
     * @hidden @internal
315
     */
316
    public onFilteringIconClick(event) {
UNCOV
317
        event.stopPropagation();
×
UNCOV
318
        this.grid.filteringService.toggleFilterDropdown(this.nativeElement, this.column);
×
319
    }
320

321
    /**
322
     * @hidden @internal
323
     */
324
    public onSortingIconClick(event) {
UNCOV
325
        event.stopPropagation();
×
UNCOV
326
        this.triggerSort();
×
327
    }
328

329
    protected getSortDirection() {
330
        const expr = this.grid.sortingExpressions.find((x) => x.fieldName === this.column.field);
15✔
331
        this.sortDirection = expr ? expr.dir : SortingDirection.None;
15!
332
    }
333

334
    protected isAdvancedFilterApplied() {
UNCOV
335
        if (!this.grid.advancedFilteringExpressionsTree) {
×
UNCOV
336
            return false;
×
337
        }
338
        return !!ExpressionsTreeUtil.find(this.grid.advancedFilteringExpressionsTree, this.column.field);
×
339
    }
340

341
    private triggerSort() {
UNCOV
342
        const groupingExpr = this.grid.groupingExpressions ?
×
343
            this.grid.groupingExpressions.find((expr) => expr.fieldName === this.column.field) :
×
344
            this.grid.groupArea?.expressions ? this.grid.groupArea?.expressions.find((expr) => expr.fieldName === this.column.field) : null;
×
UNCOV
345
        const sortDir = groupingExpr ?
×
346
            this.sortDirection + 1 > SortingDirection.Desc ? SortingDirection.Asc : SortingDirection.Desc
×
347
            : this.sortDirection + 1 > SortingDirection.Desc ? SortingDirection.None : this.sortDirection + 1;
×
UNCOV
348
        this.sortDirection = sortDir;
×
UNCOV
349
        this.grid.sort({
×
350
            fieldName: this.column.field, dir: this.sortDirection, ignoreCase: this.column.sortingIgnoreCase,
351
            strategy: this.column.sortStrategy
352
        });
353
    }
354
}
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