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

IgniteUI / igniteui-angular / 30899782753

04 Aug 2026 10:14AM UTC coverage: 90.187% (-0.003%) from 90.19%
30899782753

Pull #17425

github

web-flow
Merge b8d071dbb into 0a0755cbb
Pull Request #17425: fix(grid): Recalculate horizontal size cache when scrolling horizontally with autosized columns

14972 of 17434 branches covered (85.88%)

Branch coverage included in aggregate %.

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

66 existing lines in 4 files now uncovered.

30100 of 32542 relevant lines covered (92.5%)

37585.15 hits per line

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

86.96
/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts
1
import { AfterContentInit, AfterViewInit, ChangeDetectionStrategy, Component, EventEmitter, ElementRef, HostBinding, Input, OnInit, Output, QueryList, TemplateRef, ViewChild, ViewChildren, ContentChild, createComponent, CUSTOM_ELEMENTS_SCHEMA, booleanAttribute, OnChanges, SimpleChanges, inject } from '@angular/core';
2
import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common';
3

4
import { take, takeUntil } from 'rxjs/operators';
5
import { DEFAULT_PIVOT_KEYS, IDimensionsChange, IgxFilteringService, IgxGridNavigationService, IgxGridValidationService, IgxPivotDateDimension, IgxPivotGridValueTemplateContext, IPivotConfiguration, IPivotConfigurationChangedEventArgs, IPivotDimension, IPivotGridRecord, IPivotUISettings, IPivotValue, IValuesChange, PivotDimensionType, PivotRowLayoutType, PivotSummaryPosition, PivotUtil } from 'igniteui-angular/grids/core';
6
import { IgxGridSelectionService } from 'igniteui-angular/grids/core';
7
import { GridType, IGX_GRID_BASE, IGX_GRID_SERVICE_BASE, IgxColumnTemplateContext, PivotGridType, RowType } from 'igniteui-angular/grids/core';
8
import { IgxGridCRUDService } from 'igniteui-angular/grids/core';
9
import { IgxGridSummaryService } from 'igniteui-angular/grids/core';
10
import { IgxPivotHeaderRowComponent } from './pivot-header-row.component';
11
import { IgxColumnGroupComponent } from 'igniteui-angular/grids/core';
12
import { IgxColumnComponent } from 'igniteui-angular/grids/core';
13
import { FilterMode, GridPagingMode, GridSummaryPosition } from 'igniteui-angular/grids/core';
14
import { WatchChanges } from 'igniteui-angular/grids/core';
15
import { cloneArray, ColumnType, DataUtil, DefaultDataCloneStrategy, GridColumnDataType, GridSummaryCalculationMode, IDataCloneStrategy, IFilteringExpressionsTree, IFilteringOperation, IFilteringStrategy, ISortingExpression, OverlaySettings, resizeObservable, runAfterRenderOnce, ɵSize, SortingDirection, IgxOverlayOutletDirective } from 'igniteui-angular/core';
16
import {
17
    IGridEditEventArgs,
18
    ICellPosition,
19
    IColumnMovingEndEventArgs, IColumnMovingEventArgs, IColumnMovingStartEventArgs,
20
    IColumnVisibilityChangedEventArgs,
21
    IGridEditDoneEventArgs,
22
    IGridToolbarExportEventArgs,
23
    IPinColumnCancellableEventArgs,
24
    IPinColumnEventArgs,
25
    IPinRowEventArgs,
26
    IRowDataCancelableEventArgs,
27
    IRowDataEventArgs,
28
    IRowDragEndEventArgs,
29
    IRowDragStartEventArgs
30
} from 'igniteui-angular/grids/core';
31
import { DropPosition } from 'igniteui-angular/grids/core';
32
import { DimensionValuesFilteringStrategy, NoopPivotDimensionsStrategy } from 'igniteui-angular/grids/core';
33
import { IgxGridExcelStyleFilteringComponent, IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleFilterOperationsTemplateDirective } from 'igniteui-angular/grids/core';
34
import { IgxPivotGridNavigationService } from './pivot-grid-navigation.service';
35
import { IgxPivotColumnResizingService } from 'igniteui-angular/grids/core';
36
import { State, Transaction, TransactionService, onResourceChangeHandle } from 'igniteui-angular/core';
37
import { IgxPivotFilteringService } from './pivot-filtering.service';
38
import { GridBaseAPIService } from 'igniteui-angular/grids/core';
39
import { IgxPivotRowDimensionContentComponent } from './pivot-row-dimension-content.component';
40
import { IgxPivotGridColumnResizerComponent } from 'igniteui-angular/grids/core';
41
import { PivotSortUtil } from './pivot-sort-util';
42
import { IgxPivotRowDimensionHeaderTemplateDirective, IgxPivotValueChipTemplateDirective } from './pivot-grid.directives';
43
import { IgxPivotRowPipe, IgxPivotRowExpansionPipe, IgxPivotAutoTransform, IgxPivotColumnPipe, IgxPivotGridFilterPipe, IgxPivotGridSortingPipe, IgxPivotGridColumnSortingPipe, IgxPivotCellMergingPipe, IgxPivotGridHorizontalRowGrouping } from './pivot-grid.pipes';
44
import { IgxGridRowClassesPipe, IgxGridRowStylesPipe } from 'igniteui-angular/grids/core';
45
import { IgxExcelStyleSearchComponent } from 'igniteui-angular/grids/core';
46
import { IgxPivotRowComponent } from './pivot-row.component';
47
import { IgxColumnMovingDropDirective } from 'igniteui-angular/grids/core';
48
import { IgxGridDragSelectDirective } from 'igniteui-angular/grids/core';
49
import { IgxGridBodyDirective } from 'igniteui-angular/grids/core';
50
import { IgxColumnResizingService } from 'igniteui-angular/grids/core';
51
import { IgxPivotRowHeaderGroupComponent } from './pivot-row-header-group.component';
52
import { IgxPivotRowDimensionMrlRowComponent } from './pivot-row-dimension-mrl-row.component';
53
import { IForOfDataChangingEventArgs, IgxForOfScrollSyncService, IgxForOfSyncService, IgxGridForOfDirective, IgxTemplateOutletDirective, IgxToggleDirective } from 'igniteui-angular/directives';
54
import { IgxCircularProgressBarComponent } from 'igniteui-angular/progressbar';
55
import { IgxSnackbarComponent } from 'igniteui-angular/snackbar';
56
import { IgxIconComponent } from 'igniteui-angular/icon';
57
import { IgxPivotGridRow } from './pivot-grid-row';
58
import { IgxGridBaseDirective, IgxGridRowComponent } from 'igniteui-angular/grids/grid';
59

60
let NEXT_ID = 0;
3✔
61
const MINIMUM_COLUMN_WIDTH = 200;
3✔
62
const MINIMUM_COLUMN_WIDTH_SUPER_COMPACT = 104;
3✔
63

64
/* blazorAdditionalDependency: Column */
65
/* blazorAdditionalDependency: ColumnGroup */
66
/* blazorAdditionalDependency: ColumnLayout */
67
/* blazorAdditionalDependency: GridToolbar */
68
/* blazorAdditionalDependency: GridToolbarActions */
69
/* blazorAdditionalDependency: GridToolbarTitle */
70
/* blazorAdditionalDependency: GridToolbarAdvancedFiltering */
71
/* blazorAdditionalDependency: GridToolbarExporter */
72
/* blazorAdditionalDependency: GridToolbarHiding */
73
/* blazorAdditionalDependency: GridToolbarPinning */
74
/* blazorAdditionalDependency: ActionStrip */
75
/* blazorAdditionalDependency: GridActionsBaseDirective */
76
/* blazorAdditionalDependency: GridEditingActions */
77
/* blazorAdditionalDependency: GridPinningActions */
78
/* blazorAdditionalDependency: PivotDateDimension */
79
/* blazorIndirectRender */
80
/**
81
 * Pivot Grid provides a way to present and manipulate data in a pivot table view.
82
 *
83
 * @igxModule IgxPivotGridModule
84
 * @igxGroup Grids & Lists
85
 * @igxKeywords pivot, grid, table
86
 * @igxTheme igx-grid-theme
87
 * @remarks
88
 * The Ignite UI Pivot Grid is used for grouping and aggregating simple flat data into a pivot table.  Once data
89
 * has been bound and the dimensions and values configured it can be manipulated via sorting and filtering.
90
 * @example
91
 * ```html
92
 * <igx-pivot-grid [data]="data" [pivotConfiguration]="configuration">
93
 * </igx-pivot-grid>
94
 * ```
95
 */
96
@Component({
97
    changeDetection: ChangeDetectionStrategy.OnPush,
98
    preserveWhitespaces: false,
99
    selector: 'igx-pivot-grid',
100
    templateUrl: 'pivot-grid.component.html',
101
    providers: [
102
        IgxGridCRUDService,
103
        IgxGridValidationService,
104
        IgxGridSummaryService,
105
        IgxGridSelectionService,
106
        IgxColumnResizingService,
107
        GridBaseAPIService,
108
        { provide: IGX_GRID_SERVICE_BASE, useClass: GridBaseAPIService },
109
        { provide: IGX_GRID_BASE, useExisting: IgxPivotGridComponent },
110
        { provide: IgxFilteringService, useClass: IgxPivotFilteringService },
111
        IgxGridNavigationService,
112
        IgxPivotGridNavigationService,
113
        IgxPivotColumnResizingService,
114
        IgxForOfSyncService,
115
        IgxForOfScrollSyncService
116
    ],
117
    imports: [
118
        NgClass,
119
        NgStyle,
120
        NgTemplateOutlet,
121
        IgxPivotHeaderRowComponent,
122
        IgxGridBodyDirective,
123
        IgxGridDragSelectDirective,
124
        IgxColumnMovingDropDirective,
125
        IgxGridForOfDirective,
126
        IgxTemplateOutletDirective,
127
        IgxPivotRowComponent,
128
        IgxToggleDirective,
129
        IgxCircularProgressBarComponent,
130
        IgxSnackbarComponent,
131
        IgxOverlayOutletDirective,
132
        IgxPivotGridColumnResizerComponent,
133
        IgxIconComponent,
134
        IgxPivotRowDimensionContentComponent,
135
        IgxGridExcelStyleFilteringComponent,
136
        IgxExcelStyleColumnOperationsTemplateDirective,
137
        IgxExcelStyleFilterOperationsTemplateDirective,
138
        IgxExcelStyleSearchComponent,
139
        IgxGridRowClassesPipe,
140
        IgxGridRowStylesPipe,
141
        IgxPivotRowPipe,
142
        IgxPivotRowExpansionPipe,
143
        IgxPivotAutoTransform,
144
        IgxPivotColumnPipe,
145
        IgxPivotGridFilterPipe,
146
        IgxPivotGridSortingPipe,
147
        IgxPivotGridColumnSortingPipe,
148
        IgxPivotCellMergingPipe,
149
        IgxPivotGridHorizontalRowGrouping,
150
        IgxPivotRowDimensionMrlRowComponent
151
    ],
152
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
153
})
154
export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnInit, AfterContentInit,
3✔
155
    PivotGridType, AfterViewInit, OnChanges {
156
    /* blazorSuppress */
157
    public override readonly gridAPI = inject<GridBaseAPIService<IgxGridBaseDirective & GridType>>(GridBaseAPIService);
158✔
158
    /* blazorSuppress */
159
    public override navigation = inject(IgxPivotGridNavigationService);
158✔
160
    protected override colResizingService = inject(IgxPivotColumnResizingService);
158✔
161

162
    /**
163
     * Emitted when the dimension collection is changed via the grid chip area.
164
     *
165
     * @remarks
166
     * Returns the new dimension collection and its type:
167
     * @example
168
     * ```html
169
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
170
     *              (dimensionsChange)="dimensionsChange($event)"></igx-grid>
171
     * ```
172
     */
173
    @Output()
174
    public dimensionsChange = new EventEmitter<IDimensionsChange>();
158✔
175

176
    /**
177
     * Emitted when any of the pivotConfiguration properties is changed via the grid chip area.
178
     *
179
     * @example
180
     * ```html
181
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
182
     *              (pivotConfigurationChanged)="configurationChanged($event)"></igx-grid>
183
     * ```
184
     */
185
    @Output()
186
    public pivotConfigurationChange = new EventEmitter<IPivotConfigurationChangedEventArgs>();
158✔
187

188

189
    /**
190
     * Emitted when the dimension is initialized.
191
     * @remarks
192
     * Emits the dimension that is about to be initialized.
193
     * @example
194
     * ```html
195
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
196
     *              (dimensionInit)="dimensionInit($event)"></igx-pivot-grid>
197
     * ```
198
     */
199
    @Output()
200
    public dimensionInit = new EventEmitter<IPivotDimension>();
158✔
201

202
    /**
203
     * Emitted when the value is initialized.
204
     * @remarks
205
     * Emits the value that is about to be initialized.
206
     * @example
207
     * ```html
208
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
209
     *              (valueInit)="valueInit($event)"></igx-pivot-grid>
210
     * ```
211
     */
212
    @Output()
213
    public valueInit = new EventEmitter<IPivotValue>();
158✔
214

215

216
    /**
217
     * Emitted when a dimension is sorted.
218
     *
219
     * @example
220
     * ```html
221
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
222
     *              (dimensionsSortingExpressionsChange)="dimensionsSortingExpressionsChange($event)"></igx-pivot-grid>
223
     * ```
224
     */
225
    @Output()
226
    public dimensionsSortingExpressionsChange = new EventEmitter<ISortingExpression[]>();
158✔
227

228
    /**
229
     * Emitted when the values collection is changed via the grid chip area.
230
     *
231
     * @remarks
232
     * Returns the new dimension
233
     * @example
234
     * ```html
235
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
236
     *              (valuesChange)="valuesChange($event)"></igx-grid>
237
     * ```
238
    */
239
    @Output()
240
    public valuesChange = new EventEmitter<IValuesChange>();
158✔
241

242

243
    /**
244
     * Gets the sorting expressions generated for the dimensions.
245
     *
246
     * @example
247
     * ```typescript
248
     * const expressions = this.grid.dimensionsSortingExpressions;
249
     * ```
250
     */
251
    public get dimensionsSortingExpressions() {
252
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
24✔
253
        const dimensionsSortingExpressions = PivotSortUtil.generateDimensionSortingExpressions(allEnabledDimensions);
24✔
254
        return dimensionsSortingExpressions;
24✔
255
    }
256

257
    /** @hidden @internal */
258
    @ViewChild(IgxPivotHeaderRowComponent, { static: true })
259
    public override theadRow: IgxPivotHeaderRowComponent;
260

261
    /**
262
    * @hidden @internal
263
    */
264
    @ContentChild(IgxPivotValueChipTemplateDirective, { read: IgxPivotValueChipTemplateDirective })
265
    protected valueChipTemplateDirective: IgxPivotValueChipTemplateDirective;
266

267
    /**
268
     * @hidden @internal
269
     */
270
    @ContentChild(IgxPivotRowDimensionHeaderTemplateDirective, { read: IgxPivotRowDimensionHeaderTemplateDirective })
271
    protected rowDimensionHeaderDirective: IgxPivotRowDimensionHeaderTemplateDirective;
272

273
    /**
274
     * Gets/Sets a custom template for the value chips.
275
     *
276
     * @example
277
     * ```html
278
     * <igx-pivot-grid [valueChipTemplate]="myTemplate"><igx-pivot-grid>
279
     * ```
280
     */
281
    @Input()
282
    public valueChipTemplate: TemplateRef<IgxPivotGridValueTemplateContext>;
283

284
    @Input()
285
    public rowDimensionHeaderTemplate: TemplateRef<IgxColumnTemplateContext>;
286

287
    /* mustSetInCodePlatforms: WebComponents;Blazor;React */
288
    /* @tsTwoWayProperty (true, "PivotConfigurationChange", "Detail.PivotConfiguration", false) */
289
    /**
290
     * Gets/Sets the pivot configuration with all related dimensions and values.
291
     *
292
     * @example
293
     * ```html
294
     * <igx-pivot-grid [pivotConfiguration]="config"></igx-pivot-grid>
295
     * ```
296
     */
297
    @Input()
298
    public set pivotConfiguration(value: IPivotConfiguration) {
299
        this._pivotConfiguration = value;
183✔
300
        this.emitInitEvents(this._pivotConfiguration);
183✔
301
        this.filteringExpressionsTree = PivotUtil.buildExpressionTree(value);
183✔
302
        this.setDateDimensionsLocaleData();
183✔
303
        if (!this._init) {
183✔
304
            this.setupColumns();
23✔
305
        }
306
        this.notifyChanges(true);
183✔
307
    }
308

309
    /* mustSetInCodePlatforms: WebComponents;Blazor */
310
    public get pivotConfiguration() {
311
        return this._pivotConfiguration || { rows: null, columns: null, values: null, filters: null };
1,200,148✔
312
    }
313

314
    /**
315
     * Gets/Sets whether to auto-generate the pivot configuration based on the provided data.
316
     *
317
     * @remarks
318
     * The default value is false. When set to true, it will override all dimensions and values in the pivotConfiguration.
319
     * @example
320
     * ```html
321
     * <igx-pivot-grid [data]="Data" [autoGenerateConfig]="true"></igx-pivot-grid>
322
     * ```
323
     */
324
    @Input({ transform: booleanAttribute })
325
    public autoGenerateConfig = false;
158✔
326

327
    @Input()
328
    /**
329
     * Gets/Sets the pivot ui settings for the pivot grid - chips and their
330
     * corresponding containers for row, filter, column dimensions and values
331
     * as well as headers for the row dimensions values.
332
     * @example
333
     * ```html
334
     * <igx-pivot-grid [pivotUI]="{ showRowHeaders: true }"></igx-pivot-grid>
335
     * ```
336
     */
337
    public set pivotUI(value: IPivotUISettings) {
338
        this._pivotUI = Object.assign(this._pivotUI, value || {});
22!
339
        this.pipeTrigger++;
22✔
340
        this.notifyChanges(true);
22✔
341
    }
342

343
    public get pivotUI() {
344
        return this._pivotUI;
162,112✔
345
    }
346

347
    /**
348
     * @hidden @internal
349
     */
350
    @HostBinding('attr.role')
351
    public role = 'grid';
158✔
352

353
    /**
354
     * Enables a super compact theme for the component.
355
     * @remarks
356
     * Overrides the grid size option if one is set.
357
     * @example
358
     * ```html
359
     * <igx-pivot-grid [superCompactMode]="true"></igx-pivot-grid>
360
     * ```
361
     */
362
    @HostBinding('class.igx-grid__pivot--super-compact')
363
    @Input()
364
    public get superCompactMode() {
365
        return this._superCompactMode;
54,710✔
366
    }
367

368
    public set superCompactMode(value) {
369
        this._superCompactMode = value;
3✔
370
    }
371

372
    /** @hidden @internal */
373
    public override get gridSize() {
374
        if (this.superCompactMode) {
708✔
375
            return ɵSize.Small;
4✔
376
        }
377
        return super.gridSize;
704✔
378
    }
379

380

381
    /**
382
     * Gets/Sets the values clone strategy of the pivot grid when assigning them to different dimensions.
383
     *
384
     * @example
385
     * ```html
386
     *  <igx-pivot-grid #grid [data]="localData" [pivotValueCloneStrategy]="customCloneStrategy"></igx-pivot-grid>
387
     * ```
388
     * @hidden @internal
389
     */
390
    @Input()
391
    public get pivotValueCloneStrategy(): IDataCloneStrategy {
392
        return this._pivotValueCloneStrategy;
5,881✔
393
    }
394

395
    public set pivotValueCloneStrategy(strategy: IDataCloneStrategy) {
396
        if (strategy) {
×
397
            this._pivotValueCloneStrategy = strategy;
×
398
        }
399
    }
400

401
    /**
402
     * @hidden @internal
403
     */
404
    @ViewChild('record_template', { read: TemplateRef, static: true })
405
    public recordTemplate: TemplateRef<any>;
406

407
    /**
408
     * @hidden @internal
409
     */
410
    @ViewChild(IgxPivotRowDimensionMrlRowComponent, { read: IgxPivotRowDimensionMrlRowComponent })
411
    public rowDimensionMrlComponent: IgxPivotRowDimensionMrlRowComponent;
412

413
    /**
414
     * @hidden @internal
415
     */
416
    @ViewChild('headerTemplate', { read: TemplateRef, static: true })
417
    public headerTemplate: TemplateRef<any>;
418

419
    /**
420
     * @hidden @internal
421
     */
422
    @ViewChildren('rowDimensionContainer', { read: ElementRef })
423
    public rowDimensionContainer: QueryList<ElementRef<any>>;
424

425
    /**
426
     * @hidden @internal
427
     */
428
    @ViewChild(IgxPivotGridColumnResizerComponent)
429
    public override resizeLine: IgxPivotGridColumnResizerComponent;
430

431
    /**
432
     * @hidden @internal
433
     */
434
    @ViewChildren(IgxGridExcelStyleFilteringComponent, { read: IgxGridExcelStyleFilteringComponent })
435
    public override excelStyleFilteringComponents: QueryList<IgxGridExcelStyleFilteringComponent>;
436

437
    /**
438
     * @hidden @internal
439
     */
440
    @ViewChildren(IgxPivotRowDimensionContentComponent)
441
    protected rowDimensionContentCollection: QueryList<IgxPivotRowDimensionContentComponent>;
442

443
    /**
444
     * @hidden @internal
445
     */
446
    public override get minColumnWidth() {
447
        if (this.superCompactMode) {
52,974✔
448
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
31✔
449
        } else {
450
            return MINIMUM_COLUMN_WIDTH;
52,943✔
451
        }
452
    }
453

454
    /**
455
     * @hidden @internal
456
     */
457
    @ViewChildren('verticalRowDimScrollContainer', { read: IgxGridForOfDirective })
458
    public verticalRowDimScrollContainers: QueryList<IgxGridForOfDirective<any, any[]>>;
459

460
    /**
461
     * @hidden @internal
462
     */
463
    @ViewChildren(IgxPivotRowDimensionMrlRowComponent)
464
    public rowDimensionMrlRowsCollection: QueryList<IgxPivotRowDimensionMrlRowComponent>;
465

466
    /**
467
     * @hidden @internal
468
     */
469
    @Input()
470
    public override addRowEmptyTemplate: TemplateRef<void>;
471

472
    /**
473
     * @hidden @internal
474
     */
475
    @Input()
476
    public override autoGenerateExclude: string[] = [];
158✔
477

478
    /**
479
     * @hidden @internal
480
     */
481
    @Input()
482
    public override snackbarDisplayTime = 6000;
158✔
483

484
    /**
485
     * @hidden @internal
486
     */
487
    @Output()
488
    public override cellEdit = new EventEmitter<IGridEditEventArgs>();
158✔
489

490
    /**
491
     * @hidden @internal
492
     */
493
    @Output()
494
    public override cellEditDone = new EventEmitter<IGridEditDoneEventArgs>();
158✔
495

496
    /**
497
     * @hidden @internal
498
     */
499
    @Output()
500
    public override cellEditEnter = new EventEmitter<IGridEditEventArgs>();
158✔
501

502
    /**
503
     * @hidden @internal
504
     */
505
    @Output()
506
    public override cellEditExit = new EventEmitter<IGridEditDoneEventArgs>();
158✔
507

508
    /**
509
     * @hidden @internal
510
     */
511
    @Output()
512
    public override columnMovingStart = new EventEmitter<IColumnMovingStartEventArgs>();
158✔
513

514
    /**
515
     * @hidden @internal
516
     */
517
    @Output()
518
    public override columnMoving = new EventEmitter<IColumnMovingEventArgs>();
158✔
519

520
    /**
521
     * @hidden @internal
522
     */
523
    @Output()
524
    public override columnMovingEnd = new EventEmitter<IColumnMovingEndEventArgs>();
158✔
525

526
    /**
527
     * @hidden @internal
528
     */
529
    @Output()
530
    public override columnPin = new EventEmitter<IPinColumnCancellableEventArgs>();
158✔
531

532
    /**
533
     * @hidden @internal
534
     */
535
    @Output()
536
    public override columnPinned = new EventEmitter<IPinColumnEventArgs>();
158✔
537

538
    /**
539
     * @hidden @internal
540
     */
541
    @Output()
542
    public override rowAdd = new EventEmitter<IRowDataCancelableEventArgs>();
158✔
543

544
    /**
545
     * @hidden @internal
546
     */
547
    @Output()
548
    public override rowAdded = new EventEmitter<IRowDataEventArgs>();
158✔
549

550
    /**
551
     * @hidden @internal
552
     */
553
    @Output()
554
    public override rowDeleted = new EventEmitter<IRowDataEventArgs>();
158✔
555

556
    /**
557
     * @hidden @internal
558
     */
559
    @Output()
560
    public override rowDelete = new EventEmitter<IRowDataCancelableEventArgs>();
158✔
561

562
    /**
563
     * @hidden @internal
564
     */
565
    @Output()
566
    public override rowDragStart = new EventEmitter<IRowDragStartEventArgs>();
158✔
567

568
    /**
569
     * @hidden @internal
570
     */
571
    @Output()
572
    public override rowDragEnd = new EventEmitter<IRowDragEndEventArgs>();
158✔
573

574
    /**
575
     * @hidden @internal
576
     */
577
    @Output()
578
    public override rowEditEnter = new EventEmitter<IGridEditEventArgs>();
158✔
579

580
    /**
581
     * @hidden @internal
582
     */
583
    @Output()
584
    public override rowEdit = new EventEmitter<IGridEditEventArgs>();
158✔
585

586
    /**
587
     * @hidden @internal
588
     */
589
    @Output()
590
    public override rowEditDone = new EventEmitter<IGridEditDoneEventArgs>();
158✔
591

592
    /**
593
     * @hidden @internal
594
     */
595
    @Output()
596
    public override rowEditExit = new EventEmitter<IGridEditDoneEventArgs>();
158✔
597

598
    /**
599
     * @hidden @internal
600
     */
601
    @Output()
602
    public override rowPinning = new EventEmitter<IPinRowEventArgs>();
158✔
603

604
    /**
605
     * @hidden @internal
606
     */
607
    @Output()
608
    public override rowPinned = new EventEmitter<IPinRowEventArgs>();
158✔
609

610
    /** @hidden @internal */
611
    public columnGroupStates = new Map<string, boolean>();
158✔
612
    /** @hidden @internal */
613
    public dimensionDataColumns: any[];
614
    /** @hidden @internal */
615
    public get pivotKeys() {
616
        return this.pivotConfiguration.pivotKeys || DEFAULT_PIVOT_KEYS;
216,582✔
617
    }
618
    /** @hidden @internal */
619
    public override get type(): GridType["type"] {
620
        return 'pivot';
6,749✔
621
    }
622

623
    /**
624
     * @hidden @internal
625
     */
626
    public override dragRowID = null;
158✔
627

628
    /**
629
    * @hidden @internal
630
    */
631
    public override get rootSummariesEnabled(): boolean {
632
        return false;
6,384✔
633
    }
634

635
    /**
636
     * @hidden @internal
637
     */
638
    public rowDimensionResizing = true;
158✔
639

640
    private _emptyRowDimension: IPivotDimension = { memberName: '', enabled: true, level: 0 };
158✔
641
    /**
642
     * @hidden @internal
643
     */
644
    public get emptyRowDimension(): IPivotDimension {
645
        return this._emptyRowDimension;
3,737✔
646
    }
647

648
    protected _pivotValueCloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy();
158✔
649
    protected override _defaultExpandState = false;
158✔
650
    protected override _filterStrategy: IFilteringStrategy = new DimensionValuesFilteringStrategy();
158✔
651
    protected regroupTrigger = 0;
158✔
652
    private _data;
653
    private _pivotConfiguration: IPivotConfiguration = { rows: null, columns: null, values: null, filters: null };
158✔
654
    private p_id = `igx-pivot-grid-${NEXT_ID++}`;
158✔
655
    private _superCompactMode = false;
158✔
656
    private _pivotUI: IPivotUISettings = {
158✔
657
        showConfiguration: true,
658
        showRowHeaders: false,
659
        rowLayout: PivotRowLayoutType.Vertical,
660
        horizontalSummariesPosition: PivotSummaryPosition.Bottom
661
    };
662
    private _sortableColumns = true;
158✔
663
    private _visibleRowDimensions: IPivotDimension[] = [];
158✔
664
    private _shouldUpdateSizes = false;
158✔
665

666
    /**
667
    * Gets/Sets the default expand state for all rows.
668
    */
669
    @Input({ transform: booleanAttribute })
670
    public get defaultExpandState() {
671
        return this._defaultExpandState;
2,800✔
672
    }
673

674
    public set defaultExpandState(val: boolean) {
675
        this._defaultExpandState = val;
148✔
676
    }
677

678
    /**
679
     * @hidden @internal
680
     */
681
    @Input()
682
    public override get pagingMode(): GridPagingMode {
683
        return 'local';
×
684
    }
685

686
    public override set pagingMode(_val: GridPagingMode) {
687
    }
688

689
    /**
690
     * @hidden @internal
691
     */
692
    @WatchChanges()
693
    @Input({ transform: booleanAttribute })
694
    public override get hideRowSelectors(): boolean {
695
        return false;
×
696
    }
697

698
    public override set hideRowSelectors(_value: boolean) {
699
    }
700

701
    /**
702
     * @hidden @internal
703
     */
704
    public override autoGenerate = true;
158✔
705

706
    /**
707
     * @hidden @internal
708
     */
709
    public override get actionStrip() {
710
        return undefined as any;
1,158✔
711
    }
712

713
    /**
714
     * @hidden @internal
715
     * @deprecated in version 18.2.0. This property is no longer supported.
716
     */
717
    public override get shouldGenerate(): boolean {
718
        return false;
×
719
    }
720

721
    public override set shouldGenerate(value: boolean) {
722
    }
723

724
    /**
725
     * @hidden @internal
726
     */
727
    public override moving = false;
158✔
728

729
    /**
730
     * @hidden @internal
731
     */
732
    public override toolbarExporting = new EventEmitter<IGridToolbarExportEventArgs>();
158✔
733

734
    /**
735
     * @hidden @internal
736
     */
737
    @Input({ transform: booleanAttribute })
738
    public override get rowDraggable(): boolean {
739
        return false;
×
740
    }
741

742

743
    public override set rowDraggable(_val: boolean) {
744
    }
745

746
    /**
747
     * @hidden @internal
748
     */
749
    @Input({ transform: booleanAttribute })
750
    public override get allowAdvancedFiltering() {
751
        return false;
×
752
    }
753

754
    public override set allowAdvancedFiltering(_value) {
755
    }
756

757
    /**
758
     * @hidden @internal
759
     */
760
    @Input()
761
    public override get filterMode() {
762
        return FilterMode.quickFilter;
×
763
    }
764

765
    public override set filterMode(_value: FilterMode) {
766
    }
767

768
    /**
769
     * @hidden @internal
770
     */
771
    @Input({ transform: booleanAttribute })
772
    public override get allowFiltering() {
773
        return false;
48,808✔
774
    }
775

776
    public override set allowFiltering(_value) {
777
    }
778

779
    /**
780
     * @hidden @internal
781
     */
782
    @Input()
783
    public override get page(): number {
784
        return 0;
×
785
    }
786

787
    public override set page(_val: number) {
788
    }
789

790
    /**
791
     * @hidden @internal
792
     */
793
    @Input()
794
    public override get perPage(): number {
795
        return 0;
×
796
    }
797

798
    public override set perPage(_val: number) {
799
    }
800

801
    /**
802
     * @hidden @internal
803
     */
804
    public override get pinnedColumns(): IgxColumnComponent[] {
805
        return [];
13✔
806
    }
807

808
    /**
809
    * @hidden @internal
810
    */
811
    public override get unpinnedColumns(): IgxColumnComponent[] {
812
        return super.unpinnedColumns;
34,633✔
813
    }
814

815
    /**
816
    * @hidden @internal
817
    */
818
    public override get unpinnedDataView(): any[] {
819
        return super.unpinnedDataView;
×
820
    }
821

822
    /**
823
    * @hidden @internal
824
    */
825
    public override get unpinnedWidth() {
826
        return super.unpinnedWidth;
31,029✔
827
    }
828

829
    /**
830
     * @hidden @internal
831
     */
832
    public override get pinnedStartWidth() {
833
        return super.pinnedStartWidth;
3,370✔
834
    }
835

836
    /**
837
     * @hidden @internal
838
     */
839
    @Input()
840
    public override set summaryRowHeight(_value: number) {
841
    }
842

843
    public override get summaryRowHeight(): number {
844
        return 0;
681✔
845
    }
846

847
    /**
848
     * @hidden @internal
849
     */
850
    public override get transactions(): TransactionService<Transaction, State> {
851
        return this._transactions;
255,276✔
852
    }
853

854

855

856
    /**
857
     * @hidden @internal
858
     */
859
    public override get dragIndicatorIconTemplate(): TemplateRef<any> {
860
        return;
×
861
    }
862

863
    public override set dragIndicatorIconTemplate(_val: TemplateRef<any>) {
864
    }
865

866
    /**
867
     * @hidden @internal
868
     */
869
    @WatchChanges()
870
    @Input({ transform: booleanAttribute })
871
    public override get rowEditable(): boolean {
872
        return;
298,495✔
873
    }
874

875
    public override set rowEditable(_val: boolean) {
876
    }
877

878
    /**
879
     * @hidden @internal
880
     */
881
    @Input()
882
    public override get pinning() {
883
        return {};
198,758✔
884
    }
885
    public override set pinning(_value) {
886
    }
887

888
    /**
889
     * @hidden @internal
890
     */
891
    @Input()
892
    public override get summaryPosition() {
893
        return;
×
894
    }
895

896
    public override set summaryPosition(_value: GridSummaryPosition) {
897
    }
898

899
    /**
900
     * @hidden @internal
901
     */
902
    @Input()
903
    public override get summaryCalculationMode() {
904
        return;
×
905
    }
906

907
    public override set summaryCalculationMode(_value: GridSummaryCalculationMode) {
908
    }
909

910
    /**
911
     * @hidden @internal
912
     */
913
    @Input({ transform: booleanAttribute })
914
    public override get showSummaryOnCollapse() {
915
        return;
×
916
    }
917

918
    public override set showSummaryOnCollapse(_value: boolean) {
919
    }
920

921
    /**
922
     * @hidden @internal
923
     */
924
    public override get hiddenColumnsCount(): number {
925
        return 0;
×
926
    }
927

928
    /**
929
     * @hidden @internal
930
     */
931
    public override get pinnedColumnsCount(): number {
932
        return 0;
×
933
    }
934

935
    /**
936
     * @hidden @internal
937
     */
938
    @Input({ transform: booleanAttribute })
939
    public override get batchEditing(): boolean {
940
        return false;
×
941
    }
942

943
    public override set batchEditing(_val: boolean) {
944
    }
945

946
    /* csSuppress */
947
    public override get selectedRows(): any[] {
948
        if (this.selectionService.getSelectedRows().length === 0) {
19✔
949
            return [];
4✔
950
        }
951
        const selectedRowIds = [];
15✔
952
        this.dataView.forEach(record => {
15✔
953
            const prev = [];
182✔
954
            for (const dim of this.rowDimensions) {
182✔
955
                let currDim = dim;
345✔
956
                let shouldBreak = false;
345✔
957
                do {
345✔
958
                    const key = PivotUtil.getRecordKey(record, currDim);
651✔
959
                    if (this.selectionService.isPivotRowSelected(key) && !selectedRowIds.find(x => x === record)) {
651✔
960
                        selectedRowIds.push(record);
29✔
961
                        shouldBreak = true;
29✔
962
                        break;
29✔
963
                    }
964
                    currDim = currDim.childLevel;
622✔
965
                } while (currDim);
966
                prev.push(dim);
345✔
967
                if (shouldBreak) {
345✔
968
                    break;
29✔
969
                }
970
            }
971

972
        });
973

974
        return selectedRowIds;
15✔
975
    }
976

977
    /**
978
     * @hidden
979
     */
980
    public override ngOnInit() {
981
        // pivot grid always generates columns automatically.
982
        this.autoGenerate = true;
158✔
983
        super.ngOnInit();
158✔
984
    }
985

986
    /**
987
     * @hidden
988
     */
989
    public override ngAfterContentInit() {
990
        // ignore any user defined columns and auto-generate based on pivot config.
991
        this.updateColumns([]);
158✔
992
        Promise.resolve().then(() => {
158✔
993
            if (this.autoGenerateConfig) {
158!
994
                this.generateConfig();
×
995
            }
996
            this.setupColumns();
158✔
997
            // Bind to onResourceChange after the columns have initialized the first time to avoid premature initialization.
998
            onResourceChangeHandle(this.destroy$, () => {
158✔
999
                this.setDateDimensionsLocaleData();
1✔
1000
                // Since the columns are kinda static, due to assigning DisplayName on init, they need to be regenerated.
1001
                Promise.resolve().then(() => {
1✔
1002
                    this.setupColumns();
1✔
1003
                });
1004
            }, this);
1005
        });
1006
        if (this.valueChipTemplateDirective) {
158!
UNCOV
1007
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
×
1008
        }
1009
        if (this.rowDimensionHeaderDirective) {
158!
UNCOV
1010
            this.rowDimensionHeaderTemplate = this.rowDimensionHeaderDirective.template;
×
1011
        }
1012
    }
1013

1014
    /**
1015
     * @hidden @internal
1016
     */
1017
    public override ngAfterViewInit() {
1018
        Promise.resolve().then(() => {
158✔
1019
            super.ngAfterViewInit();
158✔
1020
        });
1021

1022
    }
1023

1024
    /**
1025
     * @hidden @internal
1026
     */
1027
    public ngOnChanges(changes: SimpleChanges) {
1028
        if (changes.superCompactMode && !changes.superCompactMode.isFirstChange()) {
209!
UNCOV
1029
            this._shouldUpdateSizes = true;
×
UNCOV
1030
            resizeObservable(this.verticalScrollContainer.displayContainer).pipe(take(1), takeUntil(this.destroy$)).subscribe(() => this.resizeNotify.next());
×
1031
        }
1032
    }
1033

1034
    /**
1035
     * Notifies for dimension change.
1036
     */
1037
    public notifyDimensionChange(regenerateColumns = false) {
×
1038
        if (regenerateColumns) {
19✔
1039
            this.setupColumns();
19✔
1040
        }
1041
        this.pipeTrigger++;
19✔
1042
        this.cdr.detectChanges();
19✔
1043
    }
1044

1045
    /**
1046
     * Gets the full list of dimensions.
1047
     *
1048
     * @example
1049
     * ```typescript
1050
     * const dimensions = this.grid.allDimensions;
1051
     * ```
1052
     */
1053
    public get allDimensions() {
1054
        const config = this._pivotConfiguration;
1,123✔
1055
        if (!config) return [];
1,123✔
1056
        return (config.rows || []).concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
2,687!
1057
    }
1058

1059
    protected get allVisibleDimensions() {
1060
        const config = this._pivotConfiguration;
310✔
1061
        if (!config) return [];
310✔
1062
        const uniqueVisibleRowDims = this.visibleRowDimensions.filter(dim => !config.rows.find(configRow => configRow.memberName === dim.memberName));
338✔
1063
        const rows = (config.rows || []).concat(...uniqueVisibleRowDims);
306!
1064
        return rows.concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
890!
1065
    }
1066

1067
    protected override get shouldResize(): boolean {
1068
        if (!this.dataRowList.first?.cells || this.dataRowList.first.cells.length === 0) {
146!
UNCOV
1069
            return false;
×
1070
        }
1071
        const isSizePropChanged = super.shouldResize;
146✔
1072
        if (isSizePropChanged || this._shouldUpdateSizes) {
146✔
1073
            this._shouldUpdateSizes = false;
60✔
1074
            return true;
60✔
1075
        }
1076
        return false;
86✔
1077
    }
1078

1079
    protected get emptyBottomSize() {
1080
        return this.totalHeight - (<any>this.verticalScroll).scrollComponent.size;
7,077✔
1081
    }
1082

1083
    /** @hidden @internal */
1084
    public createFilterESF(dropdown: any, column: ColumnType, options: OverlaySettings, shouldReatach: boolean) {
1085
        options.outlet = this.outlet;
5✔
1086
        if (dropdown) {
5✔
1087
            dropdown.initialize(column, this.overlayService);
5✔
1088
            dropdown.populateData();
5✔
1089
            if (shouldReatach) {
5✔
1090
                const id = this.overlayService.attach(dropdown.element, options);
3✔
1091
                dropdown.overlayComponentId = id;
3✔
1092
                return { id, ref: undefined };
3✔
1093
            }
1094
            return { id: dropdown.overlayComponentId, ref: undefined };
2✔
1095
        }
1096
    }
1097

1098
    /** @hidden */
1099
    public override featureColumnsWidth() {
1100
        return this.pivotRowWidths || 0;
10,208✔
1101
    }
1102

1103
    /* blazorSuppress */
1104
    /**
1105
     * Gets/Sets the value of the `id` attribute.
1106
     *
1107
     * @remarks
1108
     * If not provided it will be automatically generated.
1109
     * @example
1110
     * ```html
1111
     * <igx-pivot-grid [id]="'igx-pivot-1'" [data]="Data"></igx-pivot-grid>
1112
     * ```
1113
     */
1114
    @HostBinding('attr.id')
1115
    @Input()
1116
    public get id(): string {
1117
        return this.p_id;
86,312✔
1118
    }
1119
    /* blazorSuppress */
1120
    public set id(value: string) {
UNCOV
1121
        this.p_id = value;
×
1122
    }
1123

1124
    /* treatAsRef */
1125
    /* blazorAlternateType: object */
1126
    /**
1127
     * Gets/Sets the array of data that populates the component.
1128
     * ```html
1129
     * <igx-pivot-grid [data]="Data"></igx-pivot-grid>
1130
     * ```
1131
     */
1132
    @Input()
1133
    public set data(value: any[] | null) {
1134
        this._data = value || [];
168!
1135
        if (!this._init) {
168✔
1136
            if (this.autoGenerateConfig) {
9✔
1137
                this.generateConfig();
1✔
1138
            }
1139
            this.setupColumns();
9✔
1140
            this.reflow();
9✔
1141
        }
1142
        this.cdr.markForCheck();
168✔
1143
        if (this.height === null || this.height.indexOf('%') !== -1) {
168✔
1144
            // If the height will change based on how much data there is, recalculate sizes in igxForOf.
1145
            this.notifyChanges(true);
79✔
1146
        }
1147
    }
1148

1149
    /* treatAsRef */
1150
    /* blazorAlternateType: object */
1151
    /**
1152
     * Returns an array of data set to the component.
1153
     * ```typescript
1154
     * let data = this.grid.data;
1155
     * ```
1156
     */
1157
    public get data(): any[] | null {
1158
        return this._data;
90,343✔
1159
    }
1160

1161
    /**
1162
     * @hidden
1163
     */
1164
    public getContext(rowData, rowIndex): any {
1165
        return {
14,970✔
1166
            $implicit: rowData,
1167
            templateID: {
1168
                type: 'dataRow',
1169
                id: null
1170
            },
1171
            index: this.getDataViewIndex(rowIndex, false)
1172
        };
1173
    }
1174

1175
    /**
1176
     * @hidden @internal
1177
     */
1178
    public get pivotRowWidths() {
1179
        return this.visibleRowDimensions.length ? this.visibleRowDimensions.reduce((accumulator, dim) => accumulator + this.rowDimensionWidthToPixels(dim), 0) :
28,476✔
1180
            this.rowDimensionWidthToPixels(this.emptyRowDimension);
1181
    }
1182

1183
    /**
1184
     * @hidden @internal
1185
     */
1186
    public rowDimensionWidth(dim): string {
1187
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
44,257✔
1188
        if (isAuto) {
44,257✔
1189
            return dim.autoWidth ? dim.autoWidth + 'px' : 'fit-content';
121!
1190
        } else {
1191
            return this.rowDimensionWidthToPixels(dim) + 'px';
44,136✔
1192
        }
1193
    }
1194

1195
    /**
1196
     * @hidden @internal
1197
     */
1198
    public rowDimensionWidthToPixels(dim: IPivotDimension): number {
1199
        if (!dim?.width) {
115,059✔
1200
            return MINIMUM_COLUMN_WIDTH;
111,814✔
1201
        }
1202
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
3,245✔
1203
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
3,245✔
1204
        if (isPercent) {
3,245✔
1205
            return Math.round(parseFloat(dim.width) / 100 * this.calcWidth);
782✔
1206
        } else if (isAuto) {
2,463✔
1207
            return dim.autoWidth;
150✔
1208
        } else {
1209
            return parseInt(dim.width, 10);
2,313✔
1210
        }
1211
    }
1212

1213
    /**
1214
     * @hidden @internal
1215
     */
1216
    public reverseDimensionWidthToPercent(width: number): number {
1217
        return (width * 100 / this.calcWidth);
1✔
1218
    }
1219

1220
    /** @hidden @internal */
1221
    public get pivotContentCalcWidth() {
1222
        if (!this.platform.isBrowser) {
2,800!
UNCOV
1223
            return undefined;
×
1224
        }
1225
        if (!this.visibleRowDimensions.length) {
2,800✔
1226
            return Math.max(0, this.calcWidth - this.pivotRowWidths);
264✔
1227
        }
1228

1229
        const totalDimWidth = this.visibleRowDimensions.length > 0 ?
2,536!
1230
            this.visibleRowDimensions.map((dim) => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur) :
4,333✔
1231
            0;
1232
        return this.calcWidth - totalDimWidth;
2,536✔
1233
    }
1234

1235
    /** @hidden @internal */
1236
    public get pivotPinnedStartWidth() {
1237
        return !this._init ? this.pinnedStartWidth : 0;
5,600✔
1238
    }
1239

1240
    /** @hidden @internal */
1241
    public get pivotPinnedEndWidth() {
1242
        return !this._init ? this.pinnedEndWidth : 0;
8,400✔
1243
    }
1244

1245
    /** @hidden @internal */
1246
    public get pivotUnpinnedWidth() {
1247
        return this.unpinnedWidth || 0;
2,800!
1248
    }
1249

1250
    /** @hidden @internal */
1251
    public get rowDimensions() {
1252
        return this.pivotConfiguration.rows?.filter(x => x.enabled) || [];
108,668✔
1253
    }
1254

1255
    /** @hidden @internal */
1256
    public set visibleRowDimensions(value: IPivotDimension[]) {
1257
        this._visibleRowDimensions = value;
901✔
1258
    }
1259

1260
    public get visibleRowDimensions() {
1261
        return this._visibleRowDimensions || this.rowDimensions;
51,767!
1262
    }
1263

1264
    /** @hidden @internal */
1265
    public get columnDimensions() {
1266
        return this.pivotConfiguration.columns?.filter(x => x.enabled) || [];
397,869✔
1267
    }
1268

1269
    /** @hidden @internal */
1270
    public get filterDimensions() {
1271
        return this.pivotConfiguration.filters?.filter(x => x.enabled) || [];
7,594✔
1272
    }
1273

1274
    /** @hidden @internal */
1275
    public get values() {
1276
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
902,461✔
1277
    }
1278

1279
    public toggleColumn(col: IgxColumnComponent) {
1280
        const state = this.columnGroupStates.get(col.field);
4✔
1281
        const newState = !state;
4✔
1282
        this.columnGroupStates.set(col.field, newState);
4✔
1283
        this.toggleRowGroup(col, newState);
4✔
1284
        this.reflow();
4✔
1285
    }
1286

1287
    /**
1288
     * @hidden @internal
1289
     */
1290
    public override isRecordPinnedByIndex(_rowIndex: number) {
UNCOV
1291
        return false;
×
1292
    }
1293

1294
    /**
1295
     * @hidden @internal
1296
     */
1297
    public override toggleColumnVisibility(_args: IColumnVisibilityChangedEventArgs) {
UNCOV
1298
        return;
×
1299
    }
1300

1301
    /**
1302
     * @hidden @internal
1303
     */
1304
    public override expandAll() {
1305
    }
1306

1307
    /**
1308
     * @hidden @internal
1309
     */
1310
    public override collapseAll() {
1311
    }
1312

1313
    /**
1314
     * @hidden @internal
1315
     */
1316
    public override expandRow(_rowID: any) {
1317
    }
1318

1319
    /**
1320
     * @hidden @internal
1321
     */
1322
    public override collapseRow(_rowID: any) {
1323
    }
1324

1325
    /**
1326
     * @hidden @internal
1327
     */
1328
    public override get pinnedRows(): IgxGridRowComponent[] {
1329
        return;
2✔
1330
    }
1331

1332
    /**
1333
     * @hidden @internal
1334
     */
1335
    @Input()
1336
    public override get totalRecords(): number {
UNCOV
1337
        return;
×
1338
    }
1339

1340
    public override set totalRecords(_total: number) {
1341
    }
1342

1343
    /**
1344
     * @hidden @internal
1345
     */
1346
    public override moveColumn(_column: IgxColumnComponent, _target: IgxColumnComponent, _pos: DropPosition = DropPosition.AfterDropTarget) {
×
1347
    }
1348

1349
    /**
1350
     * @hidden @internal
1351
     */
1352
    public override addRow(_data: any): void {
1353
    }
1354

1355
    /**
1356
     * @hidden @internal
1357
     */
1358
    public override deleteRow(_rowSelector: any): any {
1359
    }
1360

1361
    /**
1362
     * @hidden @internal
1363
     */
1364
    public override updateCell(_value: any, _rowSelector: any, _column: string): void {
1365
    }
1366

1367
    /**
1368
     * @hidden @internal
1369
     */
1370
    public override updateRow(_value: any, _rowSelector: any): void {
1371
    }
1372

1373
    /**
1374
     * @hidden @internal
1375
     */
1376
    public override enableSummaries(..._rest) {
1377
    }
1378

1379
    /**
1380
     * @hidden @internal
1381
     */
1382
    public override disableSummaries(..._rest) {
1383
    }
1384

1385
    /**
1386
     * @hidden @internal
1387
     */
1388
    public override pinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
UNCOV
1389
        return;
×
1390
    }
1391

1392
    /**
1393
     * @hidden @internal
1394
     */
1395
    public override unpinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
UNCOV
1396
        return;
×
1397
    }
1398

1399
    /**
1400
     * @hidden @internal
1401
     */
1402
    public override pinRow(_rowID: any, _index?: number, _row?: RowType): boolean {
UNCOV
1403
        return;
×
1404
    }
1405

1406
    /**
1407
     * @hidden @internal
1408
     */
1409
    public override unpinRow(_rowID: any, _row?: RowType): boolean {
UNCOV
1410
        return;
×
1411
    }
1412

1413
    /**
1414
     * @hidden @internal
1415
     */
1416
    public override get pinnedRowHeight() {
1417
        return;
3,481✔
1418
    }
1419

1420
    /**
1421
     * @hidden @internal
1422
     */
1423
    public override get hasEditableColumns(): boolean {
UNCOV
1424
        return;
×
1425
    }
1426

1427
    /**
1428
     * @hidden @internal
1429
     */
1430
    public override get hasSummarizedColumns(): boolean {
1431
        return;
5✔
1432
    }
1433

1434
    /**
1435
     * @hidden @internal
1436
     */
1437
    public override get hasMovableColumns(): boolean {
1438
        return;
55,862✔
1439
    }
1440

1441
    /**
1442
     * @hidden @internal
1443
     */
1444
    public override get pinnedDataView(): any[] {
1445
        return [];
14,970✔
1446
    }
1447

1448
    /**
1449
     * @hidden @internal
1450
     */
1451
    public override openAdvancedFilteringDialog(_overlaySettings?: OverlaySettings) {
1452
    }
1453

1454
    /**
1455
     * @hidden @internal
1456
     */
1457
    public override closeAdvancedFilteringDialog(_applyChanges: boolean) {
1458
    }
1459

1460
    /**
1461
     * @hidden @internal
1462
     */
1463
    public override endEdit(_commit = true, _event?: Event): boolean {
×
UNCOV
1464
        return;
×
1465
    }
1466

1467
    /**
1468
     * @hidden @internal
1469
     */
1470
    public override beginAddRowById(_rowID: any, _asChild?: boolean): void {
1471
    }
1472

1473
    /**
1474
     * @hidden @internal
1475
     */
1476
    public override beginAddRowByIndex(_index: number): void {
1477
    }
1478

1479
    /**
1480
     * @hidden @internal
1481
     */
1482
    public override clearSearch() { }
1483

1484
    /**
1485
    * @hidden @internal
1486
    */
1487
    public override refreshSearch(_updateActiveInfo?: boolean, _endEdit = true): number {
118✔
1488
        return 0;
1,019✔
1489
    }
1490

1491
    /**
1492
    * @hidden @internal
1493
    */
1494
    public override findNext(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
UNCOV
1495
        return 0;
×
1496
    }
1497

1498
    /**
1499
    * @hidden @internal
1500
    */
1501
    public override findPrev(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
UNCOV
1502
        return 0;
×
1503
    }
1504

1505
    /**
1506
    * @hidden @internal
1507
    */
1508
    public override getNextCell(currRowIndex: number, curVisibleColIndex: number,
1509
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
×
UNCOV
1510
        return super.getNextCell(currRowIndex, curVisibleColIndex, callback);
×
1511
    }
1512

1513
    /**
1514
    * @hidden @internal
1515
    */
1516
    public override getPreviousCell(currRowIndex: number, curVisibleColIndex: number,
1517
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
×
UNCOV
1518
        return super.getPreviousCell(currRowIndex, curVisibleColIndex, callback);
×
1519
    }
1520

1521
    /**
1522
    * @hidden @internal
1523
    */
1524
    public override getPinnedStartWidth(takeHidden = false) {
721✔
1525
        return super.getPinnedStartWidth(takeHidden);
3,359✔
1526
    }
1527

1528
    /**
1529
     * @hidden @internal
1530
     */
1531
    public override get totalHeight() {
1532
        return this.calcHeight;
13,956✔
1533
    }
1534

1535
    public getColumnGroupExpandState(col: IgxColumnComponent) {
1536
        const state = this.columnGroupStates.get(col.field);
202✔
1537
        // columns are expanded by default?
1538
        return state !== undefined && state !== null ? state : false;
202✔
1539
    }
1540

1541
    public toggleRowGroup(col: IgxColumnComponent, newState: boolean) {
1542
        if (!col) return;
5!
1543
        if (this.hasMultipleValues) {
5✔
1544
            const parentCols = col.parent ? col.parent.children.toArray() : this._autoGeneratedCols.filter(x => x.level === 0);
88!
1545
            const siblingCol = parentCols.filter(x => x.header === col.header && x !== col)[0];
8✔
1546
            const currIndex = parentCols.indexOf(col);
4✔
1547
            const siblingIndex = parentCols.indexOf(siblingCol);
4✔
1548
            if (currIndex < siblingIndex) {
4✔
1549
                // clicked on the full hierarchy header
1550
                this.resolveToggle(col, newState);
3✔
1551
                siblingCol.headerTemplate = this.headerTemplate;
3✔
1552
            } else {
1553
                // clicked on summary parent column that contains just the measures
1554
                col.headerTemplate = undefined;
1✔
1555
                this.resolveToggle(siblingCol, newState);
1✔
1556
            }
1557
        } else {
1558
            const parentCols = col.parent ? col.parent.children : this._autoGeneratedCols.filter(x => x.level === 0);
5!
1559
            const fieldColumn = parentCols.filter(x => x.header === col.header && !x.columnGroup)[0];
2✔
1560
            const groupColumn = parentCols.filter(x => x.header === col.header && x.columnGroup)[0];
2✔
1561
            this.resolveToggle(groupColumn, newState);
1✔
1562
            if (newState) {
1!
1563
                fieldColumn.headerTemplate = this.headerTemplate;
1✔
1564
            } else {
UNCOV
1565
                fieldColumn.headerTemplate = undefined;
×
1566
            }
1567
        }
1568
    }
1569

1570
    /**
1571
    * @hidden @internal
1572
    */
1573
    public override setupColumns() {
1574
        super.setupColumns();
276✔
1575
    }
1576

1577
    /**
1578
    * @hidden @internal
1579
    */
1580
    public override dataRebinding(event: IForOfDataChangingEventArgs) {
1581
        if (this.hasHorizontalLayout) {
862✔
1582
            this.dimensionDataColumns = this.generateDimensionColumns();
31✔
1583
        }
1584

1585
        super.dataRebinding(event);
862✔
1586
    }
1587

1588
    /**
1589
     * Auto-sizes row dimension cells.
1590
     *
1591
     * @remarks
1592
     * Only sizes based on the dimension cells in view.
1593
     * @example
1594
     * ```typescript
1595
     * this.grid.autoSizeRowDimension(dimension);
1596
     * ```
1597
     * @param dimension The row dimension to size.
1598
     */
1599
    public autoSizeRowDimension(dimension: IPivotDimension) {
1600
        if (this.getDimensionType(dimension) === PivotDimensionType.Row) {
2✔
1601
            const relatedDims: string[] = PivotUtil.flatten([dimension]).map((x: IPivotDimension) => x.memberName);
4✔
1602
            const contentCollection = this.getContentCollection(dimension);
2✔
1603
            const content = contentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
20✔
1604
            const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
10✔
1605
            if (this.pivotUI.showRowHeaders) {
2!
UNCOV
1606
                const dimensionHeader = this.theadRow.rowDimensionHeaders.find(x => x.column.field === dimension.memberName);
×
UNCOV
1607
                headers.push(dimensionHeader);
×
1608
            }
1609
            const autoWidth = this.getLargesContentWidth(headers);
2✔
1610
            if (dimension.width === "auto") {
2!
UNCOV
1611
                dimension.autoWidth = parseFloat(autoWidth);
×
1612
            } else {
1613
                dimension.width = autoWidth;
2✔
1614
            }
1615
            this.pipeTrigger++;
2✔
1616
            this.cdr.detectChanges();
2✔
1617
        }
1618
    }
1619

1620
    /**
1621
     * Inserts dimension in target collection by type at specified index or at the collection's end.
1622
     *
1623
     * @example
1624
     * ```typescript
1625
     * this.grid.insertDimensionAt(dimension, PivotDimensionType.Row, 1);
1626
     * ```
1627
     * @param dimension The dimension that will be added.
1628
     * @param targetCollectionType The target collection type to add to. Can be Row, Column or Filter.
1629
     * @param index The index in the collection at which to add.
1630
     * This parameter is optional. If not set it will add it to the end of the collection.
1631
     */
1632
    public insertDimensionAt(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1633
        this.setDateDimensionsLocaleData([dimension]);
12✔
1634
        const targetCollection = this.getDimensionsByType(targetCollectionType);
12✔
1635
        if (index !== undefined) {
12✔
1636
            targetCollection.splice(index, 0, dimension);
11✔
1637
        } else {
1638
            targetCollection.push(dimension);
1✔
1639
        }
1640
        if (targetCollectionType === PivotDimensionType.Column) {
12✔
1641
            this.setupColumns();
4✔
1642
        }
1643
        this.pipeTrigger++;
12✔
1644
        this.dimensionsChange.emit({ dimensions: targetCollection, dimensionCollectionType: targetCollectionType });
12✔
1645
        if (targetCollectionType === PivotDimensionType.Filter) {
12✔
1646
            this.dimensionDataColumns = this.generateDimensionColumns();
3✔
1647
            this.reflow();
3✔
1648
        }
1649
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
12✔
1650
    }
1651

1652
    /**
1653
     * Move dimension from its currently collection to the specified target collection by type at specified index or at the collection's end.
1654
     *
1655
     * @example
1656
     * ```typescript
1657
     * this.grid.moveDimension(dimension, PivotDimensionType.Row, 1);
1658
     * ```
1659
     * @param dimension The dimension that will be moved.
1660
     * @param targetCollectionType The target collection type to move it to. Can be Row, Column or Filter.
1661
     * @param index The index in the collection at which to add.
1662
     * This parameter is optional. If not set it will add it to the end of the collection.
1663
     */
1664
    public moveDimension(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1665
        const prevCollectionType = this.getDimensionType(dimension);
9✔
1666
        if (prevCollectionType === null) return;
9✔
1667
        // remove from old collection
1668
        this._removeDimensionInternal(dimension);
8✔
1669
        // add to target
1670
        this.insertDimensionAt(dimension, targetCollectionType, index);
8✔
1671

1672
        if (prevCollectionType === PivotDimensionType.Column) {
8✔
1673
            this.setupColumns();
3✔
1674
        }
1675
    }
1676

1677
    /**
1678
     * Removes dimension from its currently collection.
1679
     * @remarks
1680
     * This is different than toggleDimension that enabled/disables the dimension.
1681
     * This completely removes the specified dimension from the collection.
1682
     * @example
1683
     * ```typescript
1684
     * this.grid.removeDimension(dimension);
1685
     * ```
1686
     * @param dimension The dimension to be removed.
1687
     */
1688
    public removeDimension(dimension: IPivotDimension) {
1689
        const prevCollectionType = this.getDimensionType(dimension);
4✔
1690
        this._removeDimensionInternal(dimension);
4✔
1691
        if (prevCollectionType === PivotDimensionType.Column) {
4✔
1692
            this.setupColumns();
1✔
1693
        }
1694
        if (prevCollectionType === PivotDimensionType.Filter) {
4✔
1695
            this.reflow();
1✔
1696
        }
1697
        this.pipeTrigger++;
4✔
1698
        this.cdr.detectChanges();
4✔
1699
    }
1700

1701
    /**
1702
     * Toggles the dimension's enabled state on or off.
1703
     * @remarks
1704
     * The dimension remains in its current collection. This just changes its enabled state.
1705
     * @example
1706
     * ```typescript
1707
     * this.grid.toggleDimension(dimension);
1708
     * ```
1709
     * @param dimension The dimension to be toggled.
1710
     */
1711
    public toggleDimension(dimension: IPivotDimension) {
1712
        const dimType = this.getDimensionType(dimension);
12✔
1713
        if (dimType === null) return;
12✔
1714
        const collection = this.getDimensionsByType(dimType);
11✔
1715
        dimension.enabled = !dimension.enabled;
11✔
1716
        if (dimType === PivotDimensionType.Column) {
11✔
1717
            this.setupColumns();
5✔
1718
        }
1719
        if (!dimension.enabled && dimension.filter) {
11✔
1720
            this.filteringService.clearFilter(dimension.memberName);
1✔
1721
        }
1722
        this.pipeTrigger++;
11✔
1723
        this.dimensionsChange.emit({ dimensions: collection, dimensionCollectionType: dimType });
11✔
1724
        this.cdr.detectChanges();
11✔
1725
        if (dimType === PivotDimensionType.Filter) {
11✔
1726
            this.reflow();
3✔
1727
        }
1728
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
11✔
1729
    }
1730

1731
    /**
1732
     * Inserts value at specified index or at the end.
1733
     *
1734
     * @example
1735
     * ```typescript
1736
     * this.grid.insertValueAt(value, 1);
1737
     * ```
1738
     * @param value The value definition that will be added.
1739
     * @param index The index in the collection at which to add.
1740
     * This parameter is optional. If not set it will add it to the end of the collection.
1741
     */
1742
    public insertValueAt(value: IPivotValue, index?: number) {
1743
        if (!this.pivotConfiguration.values) {
7✔
1744
            this.pivotConfiguration.values = [];
1✔
1745
        }
1746
        const values = this.pivotConfiguration.values;
7✔
1747
        if (index !== undefined) {
7✔
1748
            values.splice(index, 0, value);
6✔
1749
        } else {
1750
            values.push(value);
1✔
1751
        }
1752
        this.setupColumns();
7✔
1753
        this.pipeTrigger++;
7✔
1754
        this.cdr.detectChanges();
7✔
1755
        this.valuesChange.emit({ values });
7✔
1756
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
7✔
1757
    }
1758

1759
    /**
1760
     * Move value from its currently at specified index or at the end.
1761
     *
1762
     * @example
1763
     * ```typescript
1764
     * this.grid.moveValue(value, 1);
1765
     * ```
1766
     * @param value The value that will be moved.
1767
     * @param index The index in the collection at which to add.
1768
     * This parameter is optional. If not set it will add it to the end of the collection.
1769
     */
1770
    public moveValue(value: IPivotValue, index?: number) {
1771
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
6✔
1772
        // remove from old index
1773
        this.removeValue(value);
5✔
1774
        // add to new
1775
        this.insertValueAt(value, index);
5✔
1776
    }
1777

1778
    /**
1779
     * Removes value from collection.
1780
     * @remarks
1781
     * This is different than toggleValue that enabled/disables the value.
1782
     * This completely removes the specified value from the collection.
1783
     * @example
1784
     * ```typescript
1785
     * this.grid.removeValue(dimension);
1786
     * ```
1787
     * @param value The value to be removed.
1788
     */
1789
    public removeValue(value: IPivotValue,) {
1790
        const values = this.pivotConfiguration.values;
6✔
1791
        const currentIndex = values.indexOf(value);
6✔
1792
        if (currentIndex !== -1) {
6✔
1793
            values.splice(currentIndex, 1);
6✔
1794
            this.setupColumns();
6✔
1795
            this.pipeTrigger++;
6✔
1796
            this.valuesChange.emit({ values });
6✔
1797
            this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
6✔
1798
        }
1799
    }
1800

1801
    /**
1802
     * Toggles the value's enabled state on or off.
1803
     * @remarks
1804
     * The value remains in its current collection. This just changes its enabled state.
1805
     * @example
1806
     * ```typescript
1807
     * this.grid.toggleValue(value);
1808
     * ```
1809
     * @param value The value to be toggled.
1810
     */
1811
    public toggleValue(value: IPivotValue) {
1812
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
7✔
1813
        value.enabled = !value.enabled;
6✔
1814
        this.setupColumns();
6✔
1815
        this.pipeTrigger++;
6✔
1816
        this.valuesChange.emit({ values: this.pivotConfiguration.values });
6✔
1817
        this.reflow();
6✔
1818
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
6✔
1819
    }
1820

1821
    /**
1822
     * Sort the dimension and its children in the provided direction.
1823
     * @example
1824
     * ```typescript
1825
     * this.grid.sortDimension(dimension, SortingDirection.Asc);
1826
     * ```
1827
     * @param value The value to be toggled.
1828
     */
1829
    public sortDimension(dimension: IPivotDimension, sortDirection: SortingDirection) {
1830
        const dimensionType = this.getDimensionType(dimension);
22✔
1831
        dimension.sortDirection = sortDirection;
22✔
1832
        // apply same sort direction to children.
1833
        let dim = dimension;
22✔
1834
        if (this.pivotUI.rowLayout === PivotRowLayoutType.Vertical) {
22✔
1835
            while (dim.childLevel) {
20✔
1836
                dim.childLevel.sortDirection = dimension.sortDirection;
6✔
1837
                dim = dim.childLevel;
6✔
1838
            }
1839
        }
1840

1841
        this.pipeTrigger++;
22✔
1842
        this.dimensionsSortingExpressionsChange.emit(this.dimensionsSortingExpressions);
22✔
1843
        if (dimensionType === PivotDimensionType.Column) {
22✔
1844
            this.setupColumns();
13✔
1845
        }
1846
        this.cdr.detectChanges();
22✔
1847
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
22✔
1848
    }
1849

1850
    /**
1851
     * Filters a single `IPivotDimension`.
1852
     *
1853
     * @example
1854
     * ```typescript
1855
     * public filter() {
1856
     *      const set = new Set();
1857
     *      set.add('Value 1');
1858
     *      set.add('Value 2');
1859
     *      this.grid1.filterDimension(this.pivotConfigHierarchy.rows[0], set, IgxStringFilteringOperand.instance().condition('in'));
1860
     * }
1861
     * ```
1862
     */
1863
    public filterDimension(dimension: IPivotDimension, value: any, conditionOrExpressionTree?: IFilteringOperation | IFilteringExpressionsTree) {
1864
        this.filteringService.filter(dimension.memberName, value, conditionOrExpressionTree);
2✔
1865
        const dimensionType = this.getDimensionType(dimension);
2✔
1866
        if (dimensionType === PivotDimensionType.Column) {
2✔
1867
            this.setupColumns();
1✔
1868
        }
1869
        this.cdr.detectChanges();
2✔
1870
    }
1871

1872
    /**
1873
     * @hidden @internal
1874
     */
1875
    public getRowDimensionByName(memberName: string) {
1876
        const visibleRows = this.pivotUI.rowLayout === PivotRowLayoutType.Vertical ?
23,733✔
1877
            this.pivotConfiguration.rows :
1878
            PivotUtil.flatten(this.pivotConfiguration.rows);
1879
        const dimIndex = visibleRows.findIndex((target) => target.memberName === memberName);
43,276✔
1880
        const dim = visibleRows[dimIndex];
23,733✔
1881
        return dim;
23,733✔
1882
    }
1883

1884
    /**
1885
     * @hidden @internal
1886
     */
1887
    public getDimensionsByType(dimension: PivotDimensionType) {
1888
        switch (dimension) {
43✔
1889
            case PivotDimensionType.Row:
1890
                if (!this.pivotConfiguration.rows) {
15!
UNCOV
1891
                    this.pivotConfiguration.rows = [];
×
1892
                }
1893
                return this.pivotConfiguration.rows;
15✔
1894
            case PivotDimensionType.Column:
1895
                if (!this.pivotConfiguration.columns) {
16!
UNCOV
1896
                    this.pivotConfiguration.columns = [];
×
1897
                }
1898
                return this.pivotConfiguration.columns;
16✔
1899
            case PivotDimensionType.Filter:
1900
                if (!this.pivotConfiguration.filters) {
11✔
1901
                    this.pivotConfiguration.filters = [];
2✔
1902
                }
1903
                return this.pivotConfiguration.filters;
11✔
1904
            default:
1905
                return null;
1✔
1906
        }
1907
    }
1908

1909
    /**
1910
     * @hidden @internal
1911
     */
1912
    public resizeRowDimensionPixels(dimension: IPivotDimension, newWidth: number) {
1913
        const isPercentageWidth = dimension.width && typeof dimension.width === 'string' && dimension.width.indexOf('%') !== -1;
5✔
1914
        if (isPercentageWidth) {
5✔
1915
            dimension.width = this.reverseDimensionWidthToPercent(newWidth).toFixed(2) + '%';
1✔
1916
        } else {
1917
            dimension.width = newWidth + 'px';
4✔
1918
        }
1919

1920
        // Notify the grid to reflow, to update if horizontal scrollbar needs to be rendered/removed.
1921
        this.pipeTrigger++;
5✔
1922
        this.cdr.detectChanges();
5✔
1923
    }
1924

1925
    /*
1926
    * @hidden
1927
    * @internal
1928
    */
1929
    protected _removeDimensionInternal(dimension) {
1930
        const prevCollectionType = this.getDimensionType(dimension);
12✔
1931
        if (prevCollectionType === null) return;
12✔
1932
        const prevCollection = this.getDimensionsByType(prevCollectionType);
11✔
1933
        const currentIndex = prevCollection.indexOf(dimension);
11✔
1934
        prevCollection.splice(currentIndex, 1);
11✔
1935
        this.pipeTrigger++;
11✔
1936
        this.cdr.detectChanges();
11✔
1937
    }
1938

1939
    protected getDimensionType(dimension: IPivotDimension): PivotDimensionType {
1940
        return PivotUtil.flatten(this.pivotConfiguration.rows).indexOf(dimension) !== -1 ? PivotDimensionType.Row :
63✔
1941
            PivotUtil.flatten(this.pivotConfiguration.columns).indexOf(dimension) !== -1 ? PivotDimensionType.Column :
40✔
1942
                (!!this.pivotConfiguration.filters && PivotUtil.flatten(this.pivotConfiguration.filters).indexOf(dimension) !== -1) ?
39✔
1943
                    PivotDimensionType.Filter : null;
1944
    }
1945

1946
    protected getPivotRowHeaderContentWidth(headerGroup: IgxPivotRowHeaderGroupComponent) {
UNCOV
1947
        const headerSizes = this.getHeaderCellWidth(headerGroup.nativeElement);
×
UNCOV
1948
        return headerSizes.width + headerSizes.padding;
×
1949
    }
1950

1951
    protected getLargesContentWidth(contents: ElementRef[]): string {
1952
        const largest = new Map<number, number>();
2✔
1953
        if (contents.length > 0) {
2✔
1954
            const cellsContentWidths = [];
2✔
1955
            contents.forEach((elem) => {
2✔
1956
                elem instanceof IgxPivotRowHeaderGroupComponent ?
10!
1957
                    cellsContentWidths.push(this.getPivotRowHeaderContentWidth(elem)) :
1958
                    cellsContentWidths.push(this.getHeaderCellWidth(elem.nativeElement).width);
1959
            });
1960
            const index = cellsContentWidths.indexOf(Math.max(...cellsContentWidths));
2✔
1961
            const cellStyle = this.document.defaultView.getComputedStyle(contents[index].nativeElement);
2✔
1962
            const cellPadding = parseFloat(cellStyle.paddingLeft) + parseFloat(cellStyle.paddingRight) +
2✔
1963
                parseFloat(cellStyle.borderLeftWidth) + parseFloat(cellStyle.borderRightWidth);
1964
            largest.set(Math.max(...cellsContentWidths), cellPadding);
2✔
1965
        }
1966
        const largestCell = Math.max(...Array.from(largest.keys()));
2✔
1967
        const width = Math.ceil(largestCell + largest.get(largestCell));
2✔
1968

1969
        if (Number.isNaN(width)) {
2!
UNCOV
1970
            return null;
×
1971
        } else {
1972
            return width + 'px';
2✔
1973
        }
1974
    }
1975

1976
    /** @hidden @internal */
1977
    public get hasHorizontalLayout() {
1978
        return this.pivotUI.rowLayout === PivotRowLayoutType.Horizontal;
116,098✔
1979
    }
1980

1981
    /**
1982
    * @hidden
1983
    */
1984
    public get hasMultipleValues() {
1985
        return this.values.length > 1;
226,573✔
1986
    }
1987

1988
    /**
1989
    * @hidden
1990
    */
1991
    public get excelStyleFilterMaxHeight() {
1992
        // max 10 rows, row size depends on grid size
1993
        const maxHeight = this.renderedRowHeight * 10;
5,597✔
1994
        return `${maxHeight}px`;
5,597✔
1995
    }
1996

1997
    /**
1998
    * @hidden
1999
    */
2000
    public get excelStyleFilterMinHeight(): string {
2001
        // min 5 rows, row size depends on grid size
2002
        const minHeight = this.renderedRowHeight * 5;
5,597✔
2003
        return `${minHeight}px`;
5,597✔
2004
    }
2005

2006
    /** @hidden @internal */
2007
    public override get activeDescendant(): string | undefined {
2008
        if (this.navigation.isRowHeaderActive || this.navigation.isRowDimensionHeaderActive) {
5,600✔
2009
            return;
376✔
2010
        }
2011
        return super.activeDescendant;
5,224✔
2012
    }
2013

2014
    /** @hidden @internal */
2015
    public get headerRowActiveDescendant() {
2016
        const activeElem = this.navigation.activeNode;
4,191✔
2017
        if (!activeElem || !Object.keys(activeElem).length || !this.navigation.isRowHeaderActive) {
4,191✔
2018
            return null;
3,940✔
2019
        }
2020

2021
        const rowDimensions = this.rowDimensionContentCollection.length > 0 ?
251✔
2022
            this.rowDimensionContentCollection.toArray() :
2023
            this.rowDimensionMrlComponent.rowDimensionContentCollection.toArray();
2024

2025
        const rowDimensionContentActive = rowDimensions.find(rd => rd && rd.headerGroups?.some(hg => hg.active));
854✔
2026
        const activeHeader = rowDimensionContentActive?.headerGroups.toArray().find(hg => hg.active);
251✔
2027

2028
        return activeHeader ? `${this.id}_${activeHeader.title}` : null;
251✔
2029
    }
2030

2031
    protected resolveToggle(groupColumn: ColumnType, state: boolean) {
2032
        if (!groupColumn) return;
8!
2033
        groupColumn.hidden = state;
8✔
2034
        this.columnGroupStates.set(groupColumn.field, state);
8✔
2035
        const childrenTotal = this.hasMultipleValues ?
8✔
2036
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === this.values.length) :
44✔
2037
            groupColumn.children.filter(x => !x.columnGroup);
3✔
2038
        const childrenSubgroups = this.hasMultipleValues ?
8✔
2039
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === 0) :
44✔
2040
            groupColumn.children.filter(x => x.columnGroup);
3✔
2041
        childrenTotal.forEach(group => {
8✔
2042
            const newState = this.columnGroupStates.get(group.field) || state;
18✔
2043
            if (newState) {
18✔
2044
                group.headerTemplate = this.headerTemplate;
11✔
2045
            } else {
2046
                group.headerTemplate = undefined;
7✔
2047
            }
2048
        });
2049
        if (!groupColumn.hidden && childrenSubgroups.length > 0) {
8✔
2050
            childrenSubgroups.forEach(group => {
1✔
2051
                const newState = this.columnGroupStates.get(group.field) || state;
3✔
2052
                this.resolveToggle(group, newState);
3✔
2053
            });
2054
        }
2055
    }
2056

2057
    protected override buildDataView(data: any[]) {
2058
        this._dataView = data;
901✔
2059
    }
2060

2061
    protected override onContentSizeChange() {
2062
        super.onContentSizeChange();
18✔
2063
        this.updateDefaultRowHeight();
18✔
2064
    }
2065

2066
    /**
2067
     * @hidden @internal
2068
     */
2069
    protected override getDataBasedBodyHeight(): number {
2070
        const dvl = this.dataView?.length || 0;
96!
2071
        return dvl < this._defaultTargetRecordNumber ? 0 : this.defaultTargetBodyHeight;
96✔
2072
    }
2073

2074
    protected override horizontalScrollHandler(event) {
2075
        const scrollLeft = event.target.scrollLeft;
2✔
2076
        this.theadRow.headerContainers.forEach(headerForOf => {
2✔
2077
            headerForOf.onHScroll(scrollLeft);
4✔
2078
        });
2079
        super.horizontalScrollHandler(event);
2✔
2080
    }
2081

2082
    protected override verticalScrollHandler(event) {
UNCOV
2083
        this.verticalRowDimScrollContainers.forEach(x => {
×
2084
            x.onScroll(event);
×
2085
        });
UNCOV
2086
        super.verticalScrollHandler(event);
×
2087
    }
2088

2089
    /**
2090
     * @hidden
2091
     */
2092
    protected override autogenerateColumns() {
2093
        let columns = [];
276✔
2094
        const data = this.gridAPI.filterDataByExpressions(this.filteringExpressionsTree);
276✔
2095
        this.dimensionDataColumns = this.generateDimensionColumns();
276✔
2096
        const flattenedColumnsWithSorting = PivotUtil.flatten(this.columnDimensions).filter(dim => dim.sortDirection);
277✔
2097
        const expressions = flattenedColumnsWithSorting.length > 0 ? PivotSortUtil.generateDimensionSortingExpressions(flattenedColumnsWithSorting) : [];
276✔
2098
        let sortedData = data;
276✔
2099
        if (expressions.length > 0) {
276✔
2100
            sortedData = DataUtil.sort(cloneArray(data), expressions, this.sortStrategy, this);
12✔
2101
        }
2102
        let fieldsMap;
2103
        if (this.pivotConfiguration.columnStrategy && this.pivotConfiguration.columnStrategy instanceof NoopPivotDimensionsStrategy) {
276✔
2104
            const fields = this.generateDataFields(sortedData);
5✔
2105
            if (fields.length === 0) return;
5✔
2106
            const rowFields = PivotUtil.flatten(this.pivotConfiguration.rows).map(x => x.memberName);
6✔
2107
            const keyFields = Object.values(this.pivotKeys);
3✔
2108
            const filteredFields = fields.filter(x => rowFields.indexOf(x) === -1 && keyFields.indexOf(x) === -1 &&
18✔
2109
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.level) === -1 &&
2110
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.records) === -1);
2111
            fieldsMap = this.generateFromData(filteredFields);
3✔
2112
        } else {
2113
            fieldsMap = PivotUtil.getFieldsHierarchy(
271✔
2114
                sortedData,
2115
                this.columnDimensions,
2116
                PivotDimensionType.Column,
2117
                this.pivotKeys,
2118
                this.pivotValueCloneStrategy
2119
            );
2120
        }
2121
        columns = this.generateColumnHierarchy(fieldsMap, sortedData);
274✔
2122
        this._autoGeneratedCols = columns;
274✔
2123
        // reset expansion states if any are stored.
2124
        this.columnGroupStates.forEach((value, key) => {
274✔
2125
            if (value) {
1✔
2126
                const primaryColumn = columns.find(x => x.field === key && x.headerTemplate === this.headerTemplate);
1✔
2127
                const groupSummaryColumn = columns.find(x => x.field === key && x.headerTemplate !== this.headerTemplate);
14✔
2128
                this.toggleRowGroup(primaryColumn, value);
1✔
2129
                if (groupSummaryColumn) {
1✔
2130
                    groupSummaryColumn.headerTemplate = this.headerTemplate;
1✔
2131
                }
2132
            }
2133
        });
2134

2135
        this.updateColumns(columns);
274✔
2136
        this.pipeTrigger++;
274✔
2137
        this.reflow();
274✔
2138
    }
2139

2140
    protected generateDimensionColumns(): IgxColumnComponent[] {
2141
        const columns = [];
310✔
2142
        this.allVisibleDimensions.forEach((dim) => {
310✔
2143
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
890✔
2144
            ref.instance.field = dim.memberName;
890✔
2145
            ref.instance.header = dim.displayName || dim.memberName;
890✔
2146
            ref.instance.headerTemplate = this.rowDimensionHeaderTemplate;
890✔
2147
            ref.instance.resizable = this.rowDimensionResizing;
890✔
2148
            ref.instance.sortable = dim.sortable === undefined ? true : dim.sortable;
890!
2149
            ref.instance.width = this.rowDimensionWidth(dim);
890✔
2150
            ref.instance.filteringIgnoreCase = false;
890✔
2151
            ref.changeDetectorRef.detectChanges();
890✔
2152
            columns.push(ref.instance);
890✔
2153
        });
2154
        return columns;
310✔
2155
    }
2156

2157
    protected override calculateGridSizes(recalcFeatureWidth = true) {
576✔
2158
        super.calculateGridSizes(recalcFeatureWidth);
576✔
2159
        if (this.hasDimensionsToAutosize) {
576✔
2160
            this.cdr.detectChanges();
2✔
2161
            runAfterRenderOnce(this.injector, () => {
2✔
2162
                requestAnimationFrame(() => {
2✔
2163
                    this.autoSizeDimensionsInView();
2✔
2164
                });
2165
            });
2166
        }
2167
    }
2168

2169
    protected getContentCollection(dimenstion: IPivotDimension) {
2170
        let contentCollection;
2171
        if (this.hasHorizontalLayout) {
3!
UNCOV
2172
            const allMrlContents = this.rowDimensionMrlRowsCollection.map(mrlRow => mrlRow.contentCells.toArray()).flat();
×
UNCOV
2173
            contentCollection = allMrlContents.filter(cell => cell.rootDimension === dimenstion);
×
2174
        } else {
2175
            contentCollection = this.rowDimensionContentCollection.toArray();
3✔
2176
        }
2177
        return contentCollection;
3✔
2178
    }
2179

2180
    protected autoSizeDimensionsInView() {
2181
        if (!this.hasDimensionsToAutosize) return;
2✔
2182
        for (const dim of this.visibleRowDimensions) {
1✔
2183
            if (dim.width === 'auto') {
1✔
2184
                const contentWidths = [];
1✔
2185
                const relatedDims = PivotUtil.flatten([dim]).map(x => x.memberName);
2✔
2186
                const contentCollection = this.getContentCollection(dim);
1✔
2187
                const content = contentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
5✔
2188
                const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
5✔
2189
                headers.forEach((header) => contentWidths.push(header?.nativeElement?.offsetWidth || 0));
5!
2190
                if (this.pivotUI.showRowHeaders) {
1!
UNCOV
2191
                    const dimensionHeader = this.theadRow.rowDimensionHeaders.find(x => x.column.field === dim.memberName);
×
UNCOV
2192
                    contentWidths.push(parseFloat(this.getLargesContentWidth([dimensionHeader])));
×
2193
                }
2194
                const max = Math.max(...contentWidths);
1✔
2195
                if (max === 0) {
1!
2196
                    // cells not in DOM yet...
UNCOV
2197
                    continue;
×
2198
                }
2199
                const maxSize = Math.ceil(Math.max(...contentWidths));
1✔
2200
                dim.autoWidth = maxSize;
1✔
2201
            }
2202
        }
2203

2204
        if (this.isColumnWidthSum) {
1!
UNCOV
2205
            this.calcWidth = this.getColumnWidthSum();
×
2206
        }
2207
    }
2208

2209
    /** @hidden @internal */
2210
    public get hasDimensionsToAutosize() {
2211
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
914✔
2212
    }
2213

2214
    protected generateFromData(fields: string[]) {
2215
        const separator = this.pivotKeys.columnDimensionSeparator;
3✔
2216
        const dataArr = fields.map(x => x.split(separator)).sort(x => x.length);
12✔
2217
        const hierarchy = new Map<string, any>();
3✔
2218
        const columnDimensions = PivotUtil.flatten(this.columnDimensions);
3✔
2219
        dataArr.forEach(arr => {
3✔
2220
            let currentHierarchy = hierarchy;
12✔
2221
            const path = [];
12✔
2222
            let index = 0;
12✔
2223
            for (const val of arr) {
12✔
2224
                path.push(val);
12✔
2225
                const newPath = path.join(separator);
12✔
2226
                let targetHierarchy = currentHierarchy.get(newPath);
12✔
2227
                if (!targetHierarchy) {
12✔
2228
                    const currentColumnDimension = columnDimensions[index];
12✔
2229
                    currentHierarchy.set(newPath, { value: newPath, expandable: !!currentColumnDimension.childLevel, children: new Map<string, any>(), dimension: currentColumnDimension });
12✔
2230
                    targetHierarchy = currentHierarchy.get(newPath);
12✔
2231
                }
2232
                currentHierarchy = targetHierarchy.children;
12✔
2233
                index++;
12✔
2234
            }
2235
        });
2236
        return hierarchy;
3✔
2237
    }
2238
    protected generateColumnHierarchy(fields: Map<string, any>, data, parent = null): IgxColumnComponent[] {
274✔
2239
        let columns = [];
338✔
2240
        if (fields.size === 0) {
338✔
2241
            this.values.forEach((value) => {
20✔
2242
                const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
21✔
2243
                let columnDataType = value.dataType || this.resolveDataTypes(data.length ? data[0][value.member] : null);
21!
2244

2245
                if (value.aggregate?.key?.toLowerCase() === 'count' && (columnDataType === GridColumnDataType.Currency || columnDataType == GridColumnDataType.Percent)) {
21!
UNCOV
2246
                    columnDataType = GridColumnDataType.Number;
×
2247
                }
2248

2249
                ref.instance.header = value.displayName;
21✔
2250
                ref.instance.field = value.member;
21✔
2251
                ref.instance.parent = parent;
21✔
2252
                ref.instance.sortable = true;
21✔
2253
                ref.instance.dataType = columnDataType;
21✔
2254
                ref.instance.formatter = value.formatter;
21✔
2255
                columns.push(ref.instance);
21✔
2256
            });
2257
            return columns;
20✔
2258
        }
2259
        const currentFields = fields;
318✔
2260
        currentFields.forEach((value) => {
318✔
2261
            let shouldGenerate = true;
1,170✔
2262
            if (data.length === 0) {
1,170!
UNCOV
2263
                shouldGenerate = false;
×
2264
            }
2265
            if (shouldGenerate && (value.children == null || value.children.length === 0 || value.children.size === 0)) {
1,170✔
2266
                const col = this.createColumnForDimension(value, data, parent, this.hasMultipleValues);
1,106✔
2267

2268
                if (!this.hasMultipleValues && this.values.length > 0) {
1,106✔
2269
                    PivotUtil.updateColumnTypeByAggregator([col], this.values[0], true);
160✔
2270
                }
2271

2272
                columns.push(col);
1,106✔
2273
                if (this.hasMultipleValues) {
1,106✔
2274
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
935✔
2275

2276
                    measureChildren.forEach((child, index) => {
935✔
2277
                        const pivotValue = this.values[index];
1,875✔
2278
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
1,875✔
2279
                    });
2280

2281
                    col.children.reset(measureChildren);
935✔
2282
                    columns = columns.concat(measureChildren);
935✔
2283
                }
2284

2285
            } else if (shouldGenerate) {
64✔
2286
                const col = this.createColumnForDimension(value, data, parent, true);
64✔
2287
                if (value.expandable) {
64✔
2288
                    col.headerTemplate = this.headerTemplate;
21✔
2289
                }
2290
                const children = this.generateColumnHierarchy(value.children, data, col);
64✔
2291
                const filteredChildren = children.filter(x => x.level === col.level + 1);
456✔
2292
                columns.push(col);
64✔
2293
                if (this.hasMultipleValues) {
64✔
2294
                    let measureChildren = this.getMeasureChildren(data, col, true, value.dimension.width);
63✔
2295
                    const nestedChildren = filteredChildren;
63✔
2296
                    //const allChildren = children.concat(measureChildren);
2297
                    col.children.reset(nestedChildren);
63✔
2298
                    columns = columns.concat(children);
63✔
2299
                    if (value.dimension.childLevel) {
63✔
2300
                        const sibling = this.createColumnForDimension(value, data, parent, true);
20✔
2301
                        columns.push(sibling);
20✔
2302

2303
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2304
                        sibling.children.reset(measureChildren);
20✔
2305
                        columns = columns.concat(measureChildren);
20✔
2306
                    }
2307

2308
                } else {
2309
                    col.children.reset(filteredChildren);
1✔
2310
                    columns = columns.concat(children);
1✔
2311
                    if (value.dimension.childLevel) {
1✔
2312
                        const sibling = this.createColumnForDimension(value, data, parent, false);
1✔
2313
                        columns.push(sibling);
1✔
2314
                    }
2315
                }
2316
            }
2317
        });
2318

2319
        return columns;
318✔
2320
    }
2321

2322

2323
    protected generateConfig() {
2324
        if (!this.data) return;
1!
2325

2326
        const data = this.data;
1✔
2327
        const fields = this.generateDataFields(data);
1✔
2328
        const columnDimensions: IPivotDimension[] = [];
1✔
2329
        const rowDimensions: IPivotDimension[] = [];
1✔
2330
        const values: IPivotValue[] = [];
1✔
2331
        let isFirstDate = true;
1✔
2332
        fields.forEach((field) => {
1✔
2333
            const dataType = this.resolveDataTypes(data[0][field]);
6✔
2334
            switch (dataType) {
6✔
2335
                case "number":
2336
                    {
2337
                        const value: IPivotValue = {
2✔
2338
                            member: field,
2339
                            displayName: field,
2340
                            dataType: dataType,
2341
                            aggregate: {
2342
                                key: 'sum',
2343
                                label: 'Sum',
2344
                                aggregatorName: "SUM"
2345
                            },
2346
                            enabled: true
2347
                        };
2348
                        values.push(value);
2✔
2349
                        break;
2✔
2350
                    }
2351
                case "date":
2352
                    {
2353
                        const dimension: IPivotDimension = new IgxPivotDateDimension(
1✔
2354
                            {
2355
                                memberName: field,
2356
                                enabled: isFirstDate,
2357
                                dataType: dataType
2358
                            }
2359
                        )
2360
                        rowDimensions.push(dimension);
1✔
2361
                        isFirstDate = false;
1✔
2362
                        break;
1✔
2363
                    }
2364
                default: {
2365
                    const dimension: IPivotDimension = {
3✔
2366
                        memberName: field,
2367
                        enabled: false,
2368
                        dataType: dataType
2369
                    };
2370
                    columnDimensions.push(dimension);
3✔
2371
                    break;
3✔
2372
                }
2373
            }
2374
        });
2375
        const config: IPivotConfiguration = {
1✔
2376
            columns: columnDimensions,
2377
            rows: rowDimensions,
2378
            values: values
2379
        };
2380
        this.pivotConfiguration = config;
1✔
2381
    }
2382

2383
    protected createColumnForDimension(value: any, data: any, parent: ColumnType, isGroup: boolean) {
2384
        const key = value.value;
1,191✔
2385
        const ref = isGroup ?
1,191✔
2386
            createComponent(IgxColumnGroupComponent, { environmentInjector: this.envInjector, elementInjector: this.injector }) :
2387
            createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2388
        ref.instance.header = parent != null ? key.split(parent.header + this.pivotKeys.columnDimensionSeparator)[1] : key;
1,191✔
2389
        ref.instance.field = key;
1,191✔
2390
        ref.instance.parent = parent;
1,191✔
2391
        if (value.dimension.width) {
1,191!
UNCOV
2392
            ref.instance.width = value.dimension.width;
×
2393
        }
2394
        const valueDefinition = this.values[0];
1,191✔
2395
        ref.instance.dataType = valueDefinition?.dataType || this.resolveDataTypes(data[0][valueDefinition?.member]);
1,191✔
2396
        ref.instance.formatter = valueDefinition?.formatter;
1,191✔
2397
        ref.instance.sortable = true;
1,191✔
2398
        ref.changeDetectorRef.detectChanges();
1,191✔
2399
        return ref.instance;
1,191✔
2400
    }
2401

2402
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
UNCOV
2403
        if (dim.width) {
×
2404
            return dim.width;
×
2405
        }
UNCOV
2406
        return this.minColumnWidth + 'px';
×
2407
    }
2408

2409
    protected getMeasureChildren(data, parent, hidden, parentWidth) {
2410
        const cols = [];
1,018✔
2411
        const count = this.values.length;
1,018✔
2412
        const childWidth = parseInt(parentWidth, 10) / count;
1,018✔
2413
        const isPercent = parentWidth && parentWidth.indexOf('%') !== -1;
1,018!
2414
        const isAuto = parentWidth && parentWidth.indexOf('auto') !== -1;
1,018!
2415
        this.values.forEach(val => {
1,018✔
2416
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2,041✔
2417
            ref.instance.header = val.displayName || val.member;
2,041✔
2418
            ref.instance.field = parent.field + this.pivotKeys.columnDimensionSeparator + val.member;
2,041✔
2419
            ref.instance.parent = parent;
2,041✔
2420
            if (parentWidth) {
2,041!
UNCOV
2421
                ref.instance.width = isAuto ? 'auto' : isPercent ? childWidth + '%' : childWidth + 'px';
×
2422
            }
2423
            ref.instance.hidden = hidden;
2,041✔
2424
            ref.instance.sortable = this._sortableColumns;
2,041✔
2425
            ref.instance.dataType = val.dataType || this.resolveDataTypes(data[0][val.member]);
2,041✔
2426
            ref.instance.formatter = val.formatter;
2,041✔
2427
            ref.changeDetectorRef.detectChanges();
2,041✔
2428
            cols.push(ref.instance);
2,041✔
2429
        });
2430
        return cols;
1,018✔
2431
    }
2432

2433
    /**
2434
    * @hidden @internal
2435
    */
2436
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2437
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2438

2439
    /**
2440
     * Gets/Sets a custom template when pivot grid is empty.
2441
     *
2442
     * @example
2443
     * ```html
2444
     * <igx-pivot-grid [emptyPivotGridTemplate]="myTemplate"><igx-pivot-grid>
2445
     * ```
2446
     */
2447
    @Input()
2448
    public emptyPivotGridTemplate: TemplateRef<void>;
2449

2450
    /**
2451
    * @hidden @internal
2452
    */
2453
    public override get template(): TemplateRef<any> {
2454
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
2,800✔
2455
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
2,800✔
2456
            // no enabled values and dimensions
2457
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
71✔
2458
        }
2459
        return super.template;
2,729✔
2460
    }
2461

2462
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2463
        const dimensions = PivotUtil.flatten(this.allDimensions);
183✔
2464
        dimensions.forEach(dim => {
183✔
2465
            this.dimensionInit.emit(dim);
656✔
2466
        });
2467
        const values = pivotConfig?.values;
183✔
2468
        values?.forEach(val => {
183✔
2469
            this.valueInit.emit(val);
328✔
2470
        });
2471
    }
2472

2473
    protected rowDimensionByName(memberName: string) {
UNCOV
2474
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2475
    }
2476

2477
    protected calculateResizerTop() {
2478
        return this.pivotUI.showRowHeaders ?
33✔
2479
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
14!
2480
            this.theadRow.nativeElement.offsetHeight;
2481
    }
2482

2483
    protected override updateDefaultRowHeight() {
2484
        super.updateDefaultRowHeight();
531✔
2485
        if (this.hasHorizontalLayout) {
531✔
2486
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2487
            this.regroupTrigger++;
14✔
2488
        } else {
2489
            this.pipeTrigger++;
517✔
2490
        }
2491
    }
2492

2493
    protected trackHorizontalRowGroup = (_index: number, rowGroup: IPivotGridRecord[]) => rowGroup[0]?.dataIndex;
158✔
2494

2495
    /**
2496
     * Sets the locale and resourceStrings data based on the grid's properties for all IgxPivotDateDimensions in the config.
2497
     * By default search all dimensions (even not enabled).
2498
     * @param entryDimensions Entry dimension on which to check for IgxPivotDateDimension instead of the default.
2499
     */
2500
    protected setDateDimensionsLocaleData(entryDimensions?: IPivotDimension[]) {
2501
        const topDimensions = entryDimensions ?? [...this.allDimensions];
196✔
2502
        for (const dim of topDimensions) {
196✔
2503
            let foundDateDim: IgxPivotDateDimension | undefined;
2504
            if (dim instanceof IgxPivotDateDimension) {
503✔
2505
                foundDateDim = dim;
1✔
2506
            } else if (dim.childLevel) {
502✔
2507
                var curChild: IPivotDimension | undefined = dim.childLevel;
166✔
2508
                while(curChild) {
166✔
2509
                    if (curChild instanceof IgxPivotDateDimension) {
168!
UNCOV
2510
                        foundDateDim = curChild;
×
UNCOV
2511
                        break;
×
2512
                    }
2513
                    curChild = curChild.childLevel;
168✔
2514
                }
2515
            }
2516

2517
            if (foundDateDim) {
503✔
2518
                foundDateDim.resourceStrings = this.resourceStrings;
1✔
2519
                if (this.locale) {
1✔
2520
                    foundDateDim.locale = this.locale;
1✔
2521
                }
2522
            }
2523
        }
2524
    }
2525

2526
    /**
2527
     * @hidden @internal
2528
     */
2529
    public createRow(index: number, data?: any): RowType {
2530
        let row: RowType;
2531

UNCOV
2532
        const dataIndex = this._getDataViewIndex(index);
×
UNCOV
2533
        const rec = data ?? this.dataView[dataIndex];
×
2534

2535

UNCOV
2536
        if (!row && rec) {
×
2537
            row = new IgxPivotGridRow(this, index, rec);
×
2538
        }
UNCOV
2539
        return row;
×
2540
    }
2541
}
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