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

IgniteUI / igniteui-angular / 28358286454

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

Pull #17246

github

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

14921 of 17392 branches covered (85.79%)

Branch coverage included in aggregate %.

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

735 existing lines in 76 files now uncovered.

29992 of 32441 relevant lines covered (92.45%)

34632.46 hits per line

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

86.79
/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, IPivotGridRecord, IPivotUISettings, IPivotValue, IValuesChange, PivotDimensionType, PivotRowLayoutType, PivotSummaryPosition, PivotUtil } from 'igniteui-angular/grids/core';
6
import { IgxGridSelectionService } from 'igniteui-angular/grids/core';
7
import { GridType, IGX_GRID_BASE, IGX_GRID_SERVICE_BASE, IgxColumnTemplateContext, PivotGridType, RowType } from 'igniteui-angular/grids/core';
8
import { IgxGridCRUDService } from 'igniteui-angular/grids/core';
9
import { IgxGridSummaryService } from 'igniteui-angular/grids/core';
10
import { IgxPivotHeaderRowComponent } from './pivot-header-row.component';
11
import { IgxColumnGroupComponent } from 'igniteui-angular/grids/core';
12
import { IgxColumnComponent } from 'igniteui-angular/grids/core';
13
import { FilterMode, GridPagingMode, GridSummaryPosition } from 'igniteui-angular/grids/core';
14
import { WatchChanges } from 'igniteui-angular/grids/core';
15
import { cloneArray, ColumnType, DataUtil, DefaultDataCloneStrategy, GridColumnDataType, GridSummaryCalculationMode, IDataCloneStrategy, IFilteringExpressionsTree, IFilteringOperation, IFilteringStrategy, ISortingExpression, OverlaySettings, resizeObservable, ɵ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
                // Columns are kinda static, due to assigning DisplayName on init, they need to be regenerated.
999
                // Use notifyDimensionChange to also increment pipeTrigger and run detectChanges synchronously,
1000
                // since this callback fires outside Angular's zone and markForCheck() alone is not enough.
NEW
1001
                this.notifyDimensionChange(true);
×
1002
            }, this);
1003
        });
1004
        if (this.valueChipTemplateDirective) {
159!
1005
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
×
1006
        }
1007
        if (this.rowDimensionHeaderDirective) {
159!
1008
            this.rowDimensionHeaderTemplate = this.rowDimensionHeaderDirective.template;
×
1009
        }
1010
    }
1011

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

1020
    }
1021

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1338
    public override set totalRecords(_total: number) {
1339
    }
1340

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1477
    /**
1478
     * @hidden @internal
1479
     */
1480
    public override clearSearch() { }
1481

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

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

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

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

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

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

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

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

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

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

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

1583
        super.dataRebinding(event);
866✔
1584
    }
1585

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2201
        if (this.isColumnWidthSum) {
1!
2202
            this.calcWidth = this.getColumnWidthSum();
×
2203
        }
2204
    }
2205

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

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

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

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

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

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

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

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

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

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

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

2316
        return columns;
319✔
2317
    }
2318

2319

2320
    protected generateConfig() {
2321
        if (!this.data) return;
1!
2322

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

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

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

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

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

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

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

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

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

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

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

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

2494
    /**
2495
     * @hidden @internal
2496
     */
2497
    public createRow(index: number, data?: any): RowType {
2498
        let row: RowType;
2499

UNCOV
2500
        const dataIndex = this._getDataViewIndex(index);
×
UNCOV
2501
        const rec = data ?? this.dataView[dataIndex];
×
2502

2503

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

© 2026 Coveralls, Inc