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

IgniteUI / igniteui-angular / 25808892300

13 May 2026 03:26PM UTC coverage: 90.167% (-0.007%) from 90.174%
25808892300

Pull #17246

github

web-flow
Merge 505fad556 into cd69e807d
Pull Request #17246: fix(pivot-grid): fix date format based on the localization

14861 of 17307 branches covered (85.87%)

Branch coverage included in aggregate %.

22 of 24 new or added lines in 3 files covered. (91.67%)

52 existing lines in 2 files now uncovered.

29904 of 32340 relevant lines covered (92.47%)

34546.75 hits per line

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

86.78
/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 { first, take, takeUntil } from 'rxjs/operators';
5
import { DEFAULT_PIVOT_KEYS, IDimensionsChange, IgxFilteringService, IgxGridNavigationService, IgxGridValidationService, IgxPivotDateDimension, IgxPivotGridValueTemplateContext, IPivotConfiguration, IPivotConfigurationChangedEventArgs, IPivotDimension, 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, ɵ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);
159✔
158
    /* blazorSuppress */
159
    public override navigation = inject(IgxPivotGridNavigationService);
159✔
160
    protected override colResizingService = inject(IgxPivotColumnResizingService);
159✔
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>();
159✔
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>();
159✔
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>();
159✔
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>();
159✔
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[]>();
159✔
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>();
159✔
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;
184✔
300
        this.emitInitEvents(this._pivotConfiguration);
184✔
301
        this.filteringExpressionsTree = PivotUtil.buildExpressionTree(value);
184✔
302
        if (!this._init) {
184✔
303
            this.setupColumns();
23✔
304
        }
305
        this.notifyChanges(true);
184✔
306
    }
307

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

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

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

342
    public get pivotUI() {
343
        return this._pivotUI;
139,121✔
344
    }
345

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

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

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

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

379

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

634
    /**
635
     * @hidden @internal
636
     */
637
    public rowDimensionResizing = true;
159✔
638

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

741

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

853

854

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

971
        });
972

973
        return selectedRowIds;
15✔
974
    }
975

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

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

1010
    /**
1011
     * @hidden @internal
1012
     */
1013
    public override ngAfterViewInit() {
1014
        Promise.resolve().then(() => {
159✔
1015
            super.ngAfterViewInit();
159✔
1016
        });
1017

1018
    }
1019

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

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

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

1055
    protected get allVisibleDimensions() {
1056
        const config = this._pivotConfiguration;
311✔
1057
        if (!config) return [];
311✔
1058
        const uniqueVisibleRowDims = this.visibleRowDimensions.filter(dim => !config.rows.find(configRow => configRow.memberName === dim.memberName));
338✔
1059
        const rows = (config.rows || []).concat(...uniqueVisibleRowDims);
307!
1060
        return rows.concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
892!
1061
    }
1062

1063
    protected override get shouldResize(): boolean {
1064
        if (!this.dataRowList.first?.cells || this.dataRowList.first.cells.length === 0) {
148!
UNCOV
1065
            return false;
×
1066
        }
1067
        const isSizePropChanged = super.shouldResize;
148✔
1068
        if (isSizePropChanged || this._shouldUpdateSizes) {
148✔
1069
            this._shouldUpdateSizes = false;
61✔
1070
            return true;
61✔
1071
        }
1072
        return false;
87✔
1073
    }
1074

1075
    protected get emptyBottomSize() {
1076
        return this.totalHeight - (<any>this.verticalScroll).scrollComponent.size;
6,050✔
1077
    }
1078

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

1094
    /** @hidden */
1095
    public override featureColumnsWidth() {
1096
        return this.pivotRowWidths || 0;
10,157✔
1097
    }
1098

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

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

1145
    /* treatAsRef */
1146
    /* blazorAlternateType: object */
1147
    /**
1148
     * Returns an array of data set to the component.
1149
     * ```typescript
1150
     * let data = this.grid.data;
1151
     * ```
1152
     */
1153
    public get data(): any[] | null {
1154
        return this._data;
80,625✔
1155
    }
1156

1157
    /**
1158
     * @hidden
1159
     */
1160
    public getContext(rowData, rowIndex): any {
1161
        return {
12,640✔
1162
            $implicit: rowData,
1163
            templateID: {
1164
                type: 'dataRow',
1165
                id: null
1166
            },
1167
            index: this.getDataViewIndex(rowIndex, false)
1168
        };
1169
    }
1170

1171
    /**
1172
     * @hidden @internal
1173
     */
1174
    public get pivotRowWidths() {
1175
        return this.visibleRowDimensions.length ? this.visibleRowDimensions.reduce((accumulator, dim) => accumulator + this.rowDimensionWidthToPixels(dim), 0) :
25,949✔
1176
            this.rowDimensionWidthToPixels(this.emptyRowDimension);
1177
    }
1178

1179
    /**
1180
     * @hidden @internal
1181
     */
1182
    public rowDimensionWidth(dim): string {
1183
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
37,255✔
1184
        if (isAuto) {
37,255✔
1185
            return dim.autoWidth ? dim.autoWidth + 'px' : 'fit-content';
81!
1186
        } else {
1187
            return this.rowDimensionWidthToPixels(dim) + 'px';
37,174✔
1188
        }
1189
    }
1190

1191
    /**
1192
     * @hidden @internal
1193
     */
1194
    public rowDimensionWidthToPixels(dim: IPivotDimension): number {
1195
        if (!dim?.width) {
100,503✔
1196
            return MINIMUM_COLUMN_WIDTH;
97,731✔
1197
        }
1198
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
2,772✔
1199
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
2,772✔
1200
        if (isPercent) {
2,772✔
1201
            return Math.round(parseFloat(dim.width) / 100 * this.calcWidth);
605✔
1202
        } else if (isAuto) {
2,167✔
1203
            return dim.autoWidth;
110✔
1204
        } else {
1205
            return parseInt(dim.width, 10);
2,057✔
1206
        }
1207
    }
1208

1209
    /**
1210
     * @hidden @internal
1211
     */
1212
    public reverseDimensionWidthToPercent(width: number): number {
1213
        return (width * 100 / this.calcWidth);
1✔
1214
    }
1215

1216
    /** @hidden @internal */
1217
    public get pivotContentCalcWidth() {
1218
        if (!this.platform.isBrowser) {
2,421!
UNCOV
1219
            return undefined;
×
1220
        }
1221
        if (!this.visibleRowDimensions.length) {
2,421✔
1222
            return Math.max(0, this.calcWidth - this.pivotRowWidths);
248✔
1223
        }
1224

1225
        const totalDimWidth = this.visibleRowDimensions.length > 0 ?
2,173!
1226
            this.visibleRowDimensions.map((dim) => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur) :
3,679✔
1227
            0;
1228
        return this.calcWidth - totalDimWidth;
2,173✔
1229
    }
1230

1231
    /** @hidden @internal */
1232
    public get pivotPinnedStartWidth() {
1233
        return !this._init ? this.pinnedStartWidth : 0;
4,842✔
1234
    }
1235

1236
    /** @hidden @internal */
1237
    public get pivotPinnedEndWidth() {
1238
        return !this._init ? this.pinnedEndWidth : 0;
7,263✔
1239
    }
1240

1241
    /** @hidden @internal */
1242
    public get pivotUnpinnedWidth() {
1243
        return this.unpinnedWidth || 0;
2,421!
1244
    }
1245

1246
    /** @hidden @internal */
1247
    public get rowDimensions() {
1248
        return this.pivotConfiguration.rows?.filter(x => x.enabled) || [];
91,396✔
1249
    }
1250

1251
    /** @hidden @internal */
1252
    public set visibleRowDimensions(value: IPivotDimension[]) {
1253
        this._visibleRowDimensions = value;
897✔
1254
    }
1255

1256
    public get visibleRowDimensions() {
1257
        return this._visibleRowDimensions || this.rowDimensions;
46,261!
1258
    }
1259

1260
    /** @hidden @internal */
1261
    public get columnDimensions() {
1262
        return this.pivotConfiguration.columns?.filter(x => x.enabled) || [];
349,792✔
1263
    }
1264

1265
    /** @hidden @internal */
1266
    public get filterDimensions() {
1267
        return this.pivotConfiguration.filters?.filter(x => x.enabled) || [];
6,788✔
1268
    }
1269

1270
    /** @hidden @internal */
1271
    public get values() {
1272
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
792,855✔
1273
    }
1274

1275
    public toggleColumn(col: IgxColumnComponent) {
1276
        const state = this.columnGroupStates.get(col.field);
4✔
1277
        const newState = !state;
4✔
1278
        this.columnGroupStates.set(col.field, newState);
4✔
1279
        this.toggleRowGroup(col, newState);
4✔
1280
        this.reflow();
4✔
1281
    }
1282

1283
    /**
1284
     * @hidden @internal
1285
     */
1286
    public override isRecordPinnedByIndex(_rowIndex: number) {
UNCOV
1287
        return false;
×
1288
    }
1289

1290
    /**
1291
     * @hidden @internal
1292
     */
1293
    public override toggleColumnVisibility(_args: IColumnVisibilityChangedEventArgs) {
UNCOV
1294
        return;
×
1295
    }
1296

1297
    /**
1298
     * @hidden @internal
1299
     */
1300
    public override expandAll() {
1301
    }
1302

1303
    /**
1304
     * @hidden @internal
1305
     */
1306
    public override collapseAll() {
1307
    }
1308

1309
    /**
1310
     * @hidden @internal
1311
     */
1312
    public override expandRow(_rowID: any) {
1313
    }
1314

1315
    /**
1316
     * @hidden @internal
1317
     */
1318
    public override collapseRow(_rowID: any) {
1319
    }
1320

1321
    /**
1322
     * @hidden @internal
1323
     */
1324
    public override get pinnedRows(): IgxGridRowComponent[] {
1325
        return;
2✔
1326
    }
1327

1328
    /**
1329
     * @hidden @internal
1330
     */
1331
    @Input()
1332
    public override get totalRecords(): number {
UNCOV
1333
        return;
×
1334
    }
1335

1336
    public override set totalRecords(_total: number) {
1337
    }
1338

1339
    /**
1340
     * @hidden @internal
1341
     */
1342
    public override moveColumn(_column: IgxColumnComponent, _target: IgxColumnComponent, _pos: DropPosition = DropPosition.AfterDropTarget) {
×
1343
    }
1344

1345
    /**
1346
     * @hidden @internal
1347
     */
1348
    public override addRow(_data: any): void {
1349
    }
1350

1351
    /**
1352
     * @hidden @internal
1353
     */
1354
    public override deleteRow(_rowSelector: any): any {
1355
    }
1356

1357
    /**
1358
     * @hidden @internal
1359
     */
1360
    public override updateCell(_value: any, _rowSelector: any, _column: string): void {
1361
    }
1362

1363
    /**
1364
     * @hidden @internal
1365
     */
1366
    public override updateRow(_value: any, _rowSelector: any): void {
1367
    }
1368

1369
    /**
1370
     * @hidden @internal
1371
     */
1372
    public override enableSummaries(..._rest) {
1373
    }
1374

1375
    /**
1376
     * @hidden @internal
1377
     */
1378
    public override disableSummaries(..._rest) {
1379
    }
1380

1381
    /**
1382
     * @hidden @internal
1383
     */
1384
    public override pinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
UNCOV
1385
        return;
×
1386
    }
1387

1388
    /**
1389
     * @hidden @internal
1390
     */
1391
    public override unpinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
UNCOV
1392
        return;
×
1393
    }
1394

1395
    /**
1396
     * @hidden @internal
1397
     */
1398
    public override pinRow(_rowID: any, _index?: number, _row?: RowType): boolean {
UNCOV
1399
        return;
×
1400
    }
1401

1402
    /**
1403
     * @hidden @internal
1404
     */
1405
    public override unpinRow(_rowID: any, _row?: RowType): boolean {
UNCOV
1406
        return;
×
1407
    }
1408

1409
    /**
1410
     * @hidden @internal
1411
     */
1412
    public override get pinnedRowHeight() {
1413
        return;
3,106✔
1414
    }
1415

1416
    /**
1417
     * @hidden @internal
1418
     */
1419
    public override get hasEditableColumns(): boolean {
UNCOV
1420
        return;
×
1421
    }
1422

1423
    /**
1424
     * @hidden @internal
1425
     */
1426
    public override get hasSummarizedColumns(): boolean {
1427
        return;
5✔
1428
    }
1429

1430
    /**
1431
     * @hidden @internal
1432
     */
1433
    public override get hasMovableColumns(): boolean {
1434
        return;
46,827✔
1435
    }
1436

1437
    /**
1438
     * @hidden @internal
1439
     */
1440
    public override get pinnedDataView(): any[] {
1441
        return [];
12,640✔
1442
    }
1443

1444
    /**
1445
     * @hidden @internal
1446
     */
1447
    public override openAdvancedFilteringDialog(_overlaySettings?: OverlaySettings) {
1448
    }
1449

1450
    /**
1451
     * @hidden @internal
1452
     */
1453
    public override closeAdvancedFilteringDialog(_applyChanges: boolean) {
1454
    }
1455

1456
    /**
1457
     * @hidden @internal
1458
     */
1459
    public override endEdit(_commit = true, _event?: Event): boolean {
×
UNCOV
1460
        return;
×
1461
    }
1462

1463
    /**
1464
     * @hidden @internal
1465
     */
1466
    public override beginAddRowById(_rowID: any, _asChild?: boolean): void {
1467
    }
1468

1469
    /**
1470
     * @hidden @internal
1471
     */
1472
    public override beginAddRowByIndex(_index: number): void {
1473
    }
1474

1475
    /**
1476
     * @hidden @internal
1477
     */
1478
    public override clearSearch() { }
1479

1480
    /**
1481
    * @hidden @internal
1482
    */
1483
    public override refreshSearch(_updateActiveInfo?: boolean, _endEdit = true): number {
119✔
1484
        return 0;
1,016✔
1485
    }
1486

1487
    /**
1488
    * @hidden @internal
1489
    */
1490
    public override findNext(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
UNCOV
1491
        return 0;
×
1492
    }
1493

1494
    /**
1495
    * @hidden @internal
1496
    */
1497
    public override findPrev(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
UNCOV
1498
        return 0;
×
1499
    }
1500

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

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

1517
    /**
1518
    * @hidden @internal
1519
    */
1520
    public override getPinnedStartWidth(takeHidden = false) {
676✔
1521
        return super.getPinnedStartWidth(takeHidden);
3,286✔
1522
    }
1523

1524
    /**
1525
     * @hidden @internal
1526
     */
1527
    public override get totalHeight() {
1528
        return this.calcHeight;
11,988✔
1529
    }
1530

1531
    public getColumnGroupExpandState(col: IgxColumnComponent) {
1532
        const state = this.columnGroupStates.get(col.field);
174✔
1533
        // columns are expanded by default?
1534
        return state !== undefined && state !== null ? state : false;
174✔
1535
    }
1536

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

1566
    /**
1567
    * @hidden @internal
1568
    */
1569
    public override setupColumns() {
1570
        super.setupColumns();
277✔
1571
    }
1572

1573
    /**
1574
    * @hidden @internal
1575
    */
1576
    public override dataRebinding(event: IForOfDataChangingEventArgs) {
1577
        if (this.hasHorizontalLayout) {
866✔
1578
            this.dimensionDataColumns = this.generateDimensionColumns();
31✔
1579
        }
1580

1581
        super.dataRebinding(event);
866✔
1582
    }
1583

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

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

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

1667
        if (prevCollectionType === PivotDimensionType.Column) {
8✔
1668
            this.setupColumns();
3✔
1669
        }
1670
    }
1671

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

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

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

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

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

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

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

1836
        this.pipeTrigger++;
22✔
1837
        this.dimensionsSortingExpressionsChange.emit(this.dimensionsSortingExpressions);
22✔
1838
        if (dimensionType === PivotDimensionType.Column) {
22✔
1839
            this.setupColumns();
13✔
1840
        }
1841
        this.cdr.detectChanges();
22✔
1842
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
22✔
1843
    }
1844

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

1867
    /**
1868
     * @hidden @internal
1869
     */
1870
    public getRowDimensionByName(memberName: string) {
1871
        const visibleRows = this.pivotUI.rowLayout === PivotRowLayoutType.Vertical ?
19,784✔
1872
            this.pivotConfiguration.rows :
1873
            PivotUtil.flatten(this.pivotConfiguration.rows);
1874
        const dimIndex = visibleRows.findIndex((target) => target.memberName === memberName);
35,826✔
1875
        const dim = visibleRows[dimIndex];
19,784✔
1876
        return dim;
19,784✔
1877
    }
1878

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

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

1915
        // Notify the grid to reflow, to update if horizontal scrollbar needs to be rendered/removed.
1916
        this.pipeTrigger++;
5✔
1917
        this.cdr.detectChanges();
5✔
1918
    }
1919

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

1934
    protected getDimensionType(dimension: IPivotDimension): PivotDimensionType {
1935
        return PivotUtil.flatten(this.pivotConfiguration.rows).indexOf(dimension) !== -1 ? PivotDimensionType.Row :
63✔
1936
            PivotUtil.flatten(this.pivotConfiguration.columns).indexOf(dimension) !== -1 ? PivotDimensionType.Column :
40✔
1937
                (!!this.pivotConfiguration.filters && PivotUtil.flatten(this.pivotConfiguration.filters).indexOf(dimension) !== -1) ?
39✔
1938
                    PivotDimensionType.Filter : null;
1939
    }
1940

1941
    protected getPivotRowHeaderContentWidth(headerGroup: IgxPivotRowHeaderGroupComponent) {
UNCOV
1942
        const headerSizes = this.getHeaderCellWidth(headerGroup.nativeElement);
×
UNCOV
1943
        return headerSizes.width + headerSizes.padding;
×
1944
    }
1945

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

1964
        if (Number.isNaN(width)) {
2!
UNCOV
1965
            return null;
×
1966
        } else {
1967
            return width + 'px';
2✔
1968
        }
1969
    }
1970

1971
    /** @hidden @internal */
1972
    public get hasHorizontalLayout() {
1973
        return this.pivotUI.rowLayout === PivotRowLayoutType.Horizontal;
100,014✔
1974
    }
1975

1976
    /**
1977
    * @hidden
1978
    */
1979
    public get hasMultipleValues() {
1980
        return this.values.length > 1;
199,655✔
1981
    }
1982

1983
    /**
1984
    * @hidden
1985
    */
1986
    public get excelStyleFilterMaxHeight() {
1987
        // max 10 rows, row size depends on grid size
1988
        const maxHeight = this.renderedRowHeight * 10;
4,839✔
1989
        return `${maxHeight}px`;
4,839✔
1990
    }
1991

1992
    /**
1993
    * @hidden
1994
    */
1995
    public get excelStyleFilterMinHeight(): string {
1996
        // min 5 rows, row size depends on grid size
1997
        const minHeight = this.renderedRowHeight * 5;
4,839✔
1998
        return `${minHeight}px`;
4,839✔
1999
    }
2000

2001
    /** @hidden @internal */
2002
    public override get activeDescendant(): string | undefined {
2003
        if (this.navigation.isRowHeaderActive || this.navigation.isRowDimensionHeaderActive) {
4,842✔
2004
            return;
286✔
2005
        }
2006
        return super.activeDescendant;
4,556✔
2007
    }
2008

2009
    /** @hidden @internal */
2010
    public get headerRowActiveDescendant() {
2011
        const activeElem = this.navigation.activeNode;
3,612✔
2012
        if (!activeElem || !Object.keys(activeElem).length || !this.navigation.isRowHeaderActive) {
3,612✔
2013
            return null;
3,432✔
2014
        }
2015

2016
        const rowDimensions = this.rowDimensionContentCollection.length > 0 ?
180✔
2017
            this.rowDimensionContentCollection.toArray() :
2018
            this.rowDimensionMrlComponent.rowDimensionContentCollection.toArray();
2019

2020
        const rowDimensionContentActive = rowDimensions.find(rd => rd && rd.headerGroups?.some(hg => hg.active));
657✔
2021
        const activeHeader = rowDimensionContentActive?.headerGroups.toArray().find(hg => hg.active);
180✔
2022

2023
        return activeHeader ? `${this.id}_${activeHeader.title}` : null;
180✔
2024
    }
2025

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

2052
    protected override buildDataView(data: any[]) {
2053
        this._dataView = data;
897✔
2054
    }
2055

2056
    protected override onContentSizeChange() {
2057
        super.onContentSizeChange();
18✔
2058
        this.updateDefaultRowHeight();
18✔
2059
    }
2060

2061
    /**
2062
     * @hidden @internal
2063
     */
2064
    protected override getDataBasedBodyHeight(): number {
2065
        const dvl = this.dataView?.length || 0;
96!
2066
        return dvl < this._defaultTargetRecordNumber ? 0 : this.defaultTargetBodyHeight;
96✔
2067
    }
2068

2069
    protected override horizontalScrollHandler(event) {
2070
        const scrollLeft = event.target.scrollLeft;
2✔
2071
        this.theadRow.headerContainers.forEach(headerForOf => {
2✔
2072
            headerForOf.onHScroll(scrollLeft);
4✔
2073
        });
2074
        super.horizontalScrollHandler(event);
2✔
2075
    }
2076

2077
    protected override verticalScrollHandler(event) {
UNCOV
2078
        this.verticalRowDimScrollContainers.forEach(x => {
×
UNCOV
2079
            x.onScroll(event);
×
2080
        });
2081
        super.verticalScrollHandler(event);
×
2082
    }
2083

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

2130
        this.updateColumns(columns);
275✔
2131
        this.pipeTrigger++;
275✔
2132
        this.reflow();
275✔
2133
    }
2134

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

2152
    protected override calculateGridSizes(recalcFeatureWidth = true) {
579✔
2153
        super.calculateGridSizes(recalcFeatureWidth);
579✔
2154
        if (this.hasDimensionsToAutosize) {
579✔
2155
            this.cdr.detectChanges();
2✔
2156
            this.zone.onStable.pipe(first()).subscribe(() => {
2✔
2157
                requestAnimationFrame(() => {
2✔
2158
                    this.autoSizeDimensionsInView();
2✔
2159
                });
2160
            });
2161
        }
2162
    }
2163

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

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

2199
        if (this.isColumnWidthSum) {
1!
UNCOV
2200
            this.calcWidth = this.getColumnWidthSum();
×
2201
        }
2202
    }
2203

2204
    /** @hidden @internal */
2205
    public get hasDimensionsToAutosize() {
2206
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
917✔
2207
    }
2208

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

2240
                if (value.aggregate?.key?.toLowerCase() === 'count' && (columnDataType === GridColumnDataType.Currency || columnDataType == GridColumnDataType.Percent)) {
21!
UNCOV
2241
                    columnDataType = GridColumnDataType.Number;
×
2242
                }
2243

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

2263
                if (!this.hasMultipleValues && this.values.length > 0) {
1,109✔
2264
                    PivotUtil.updateColumnTypeByAggregator([col], this.values[0], true);
160✔
2265
                }
2266

2267
                columns.push(col);
1,109✔
2268
                if (this.hasMultipleValues) {
1,109✔
2269
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
938✔
2270

2271
                    measureChildren.forEach((child, index) => {
938✔
2272
                        const pivotValue = this.values[index];
1,881✔
2273
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
1,881✔
2274
                    });
2275

2276
                    col.children.reset(measureChildren);
938✔
2277
                    columns = columns.concat(measureChildren);
938✔
2278
                }
2279

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

2298
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2299
                        sibling.children.reset(measureChildren);
20✔
2300
                        columns = columns.concat(measureChildren);
20✔
2301
                    }
2302

2303
                } else {
2304
                    col.children.reset(filteredChildren);
1✔
2305
                    columns = columns.concat(children);
1✔
2306
                    if (value.dimension.childLevel) {
1✔
2307
                        const sibling = this.createColumnForDimension(value, data, parent, false);
1✔
2308
                        columns.push(sibling);
1✔
2309
                    }
2310
                }
2311
            }
2312
        });
2313

2314
        return columns;
319✔
2315
    }
2316

2317

2318
    protected generateConfig() {
2319
        if (!this.data) return;
1!
2320

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

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

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

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

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

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

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

2459
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2460
        const dimensions = PivotUtil.flatten(this.allDimensions);
184✔
2461
        dimensions.forEach(dim => {
184✔
2462
            this.dimensionInit.emit(dim);
659✔
2463
        });
2464
        const values = pivotConfig?.values;
184✔
2465
        values?.forEach(val => {
184✔
2466
            this.valueInit.emit(val);
330✔
2467
        });
2468
    }
2469

2470
    protected rowDimensionByName(memberName: string) {
UNCOV
2471
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2472
    }
2473

2474
    protected calculateResizerTop() {
2475
        return this.pivotUI.showRowHeaders ?
18✔
2476
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
8!
2477
            this.theadRow.nativeElement.offsetHeight;
2478
    }
2479

2480
    protected override updateDefaultRowHeight() {
2481
        super.updateDefaultRowHeight();
535✔
2482
        if (this.hasHorizontalLayout) {
535✔
2483
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2484
            this.regroupTrigger++;
14✔
2485
        } else {
2486
            this.pipeTrigger++;
521✔
2487
        }
2488
    }
2489

2490
    /**
2491
     * @hidden @internal
2492
     */
2493
    public createRow(index: number, data?: any): RowType {
2494
        let row: RowType;
2495

UNCOV
2496
        const dataIndex = this._getDataViewIndex(index);
×
UNCOV
2497
        const rec = data ?? this.dataView[dataIndex];
×
2498

2499

UNCOV
2500
        if (!row && rec) {
×
UNCOV
2501
            row = new IgxPivotGridRow(this, index, rec);
×
2502
        }
2503
        return row;
×
2504
    }
2505
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc