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

IgniteUI / igniteui-angular / 30891705717

04 Aug 2026 08:22AM UTC coverage: 90.16% (-0.03%) from 90.187%
30891705717

Pull #15125

github

web-flow
Merge 19b57fb2e into 0a0755cbb
Pull Request #15125: refactor(*): bundle styles with components

14975 of 17448 branches covered (85.83%)

Branch coverage included in aggregate %.

30133 of 32583 relevant lines covered (92.48%)

37490.31 hits per line

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

86.96
/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.ts
1
import {
2
    AfterContentInit,
3
    AfterViewInit,
4
    booleanAttribute,
5
    ChangeDetectionStrategy,
6
    Component,
7
    ContentChild,
8
    createComponent,
9
    CUSTOM_ELEMENTS_SCHEMA,
10
    ElementRef,
11
    EventEmitter,
12
    HostBinding,
13
    inject,
14
    Input,
15
    OnChanges,
16
    OnInit,
17
    Output,
18
    QueryList,
19
    SimpleChanges,
20
    TemplateRef,
21
    ViewChild,
22
    ViewChildren,
23
    ViewEncapsulation,
24
} from '@angular/core';
25
import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
26

27
import { take, takeUntil } from 'rxjs/operators';
28
import {
29
    DEFAULT_PIVOT_KEYS,
30
    DimensionValuesFilteringStrategy,
31
    DropPosition,
32
    FilterMode,
33
    GridBaseAPIService,
34
    GridPagingMode,
35
    GridSummaryPosition,
36
    GridType,
37
    ICellPosition,
38
    IColumnMovingEndEventArgs,
39
    IColumnMovingEventArgs,
40
    IColumnMovingStartEventArgs,
41
    IColumnVisibilityChangedEventArgs,
42
    IDimensionsChange,
43
    IGridEditDoneEventArgs,
44
    IGridEditEventArgs,
45
    IGridToolbarExportEventArgs,
46
    IGX_GRID_BASE,
47
    IGX_GRID_SERVICE_BASE,
48
    IgxColumnComponent,
49
    IgxColumnGroupComponent,
50
    IgxColumnMovingDropDirective,
51
    IgxColumnResizingService,
52
    IgxColumnTemplateContext,
53
    IgxExcelStyleColumnOperationsTemplateDirective,
54
    IgxExcelStyleFilterOperationsTemplateDirective,
55
    IgxExcelStyleSearchComponent,
56
    IgxFilteringService,
57
    IgxGridBodyDirective,
58
    IgxGridCRUDService,
59
    IgxGridDragSelectDirective,
60
    IgxGridExcelStyleFilteringComponent,
61
    IgxGridNavigationService,
62
    IgxGridRowClassesPipe,
63
    IgxGridRowStylesPipe,
64
    IgxGridSelectionService,
65
    IgxGridSummaryService,
66
    IgxGridValidationService,
67
    IgxPivotColumnResizingService,
68
    IgxPivotDateDimension,
69
    IgxPivotGridColumnResizerComponent,
70
    IgxPivotGridValueTemplateContext,
71
    IPinColumnCancellableEventArgs,
72
    IPinColumnEventArgs,
73
    IPinRowEventArgs,
74
    IPivotConfiguration,
75
    IPivotConfigurationChangedEventArgs,
76
    IPivotDimension,
77
    IPivotGridRecord,
78
    IPivotUISettings,
79
    IPivotValue,
80
    IRowDataCancelableEventArgs,
81
    IRowDataEventArgs,
82
    IRowDragEndEventArgs,
83
    IRowDragStartEventArgs,
84
    IValuesChange,
85
    NoopPivotDimensionsStrategy,
86
    PivotDimensionType,
87
    PivotGridType,
88
    PivotRowLayoutType,
89
    PivotSummaryPosition,
90
    PivotUtil,
91
    RowType,
92
    WatchChanges,
93
} from 'igniteui-angular/grids/core';
94
import { IgxPivotHeaderRowComponent } from './pivot-header-row.component';
95
import {
96
    cloneArray,
97
    ColumnType,
98
    DataUtil,
99
    DefaultDataCloneStrategy,
100
    GridColumnDataType,
101
    GridSummaryCalculationMode,
102
    IDataCloneStrategy,
103
    IFilteringExpressionsTree,
104
    IFilteringOperation,
105
    IFilteringStrategy,
106
    IgxOverlayOutletDirective,
107
    ISortingExpression,
108
    onResourceChangeHandle,
109
    OverlaySettings,
110
    resizeObservable,
111
    runAfterRenderOnce,
112
    SortingDirection,
113
    State,
114
    Transaction,
115
    TransactionService,
116
    ɵSize,
117
} from 'igniteui-angular/core';
118
import { IgxPivotGridNavigationService } from './pivot-grid-navigation.service';
119
import { IgxPivotFilteringService } from './pivot-filtering.service';
120
import { IgxPivotRowDimensionContentComponent } from './pivot-row-dimension-content.component';
121
import { PivotSortUtil } from './pivot-sort-util';
122
import {
123
    IgxPivotRowDimensionHeaderTemplateDirective,
124
    IgxPivotValueChipTemplateDirective,
125
} from './pivot-grid.directives';
126
import {
127
    IgxPivotAutoTransform,
128
    IgxPivotCellMergingPipe,
129
    IgxPivotColumnPipe,
130
    IgxPivotGridColumnSortingPipe,
131
    IgxPivotGridFilterPipe,
132
    IgxPivotGridHorizontalRowGrouping,
133
    IgxPivotGridSortingPipe,
134
    IgxPivotRowExpansionPipe,
135
    IgxPivotRowPipe,
136
} from './pivot-grid.pipes';
137
import { IgxPivotRowComponent } from './pivot-row.component';
138
import { IgxPivotRowHeaderGroupComponent } from './pivot-row-header-group.component';
139
import { IgxPivotRowDimensionMrlRowComponent } from './pivot-row-dimension-mrl-row.component';
140
import {
141
    IForOfDataChangeEventArgs,
142
    IgxForOfScrollSyncService,
143
    IgxForOfSyncService,
144
    IgxGridForOfDirective,
145
    IgxTemplateOutletDirective,
146
    IgxToggleDirective,
147
} from 'igniteui-angular/directives';
148
import { IgxCircularProgressBarComponent } from 'igniteui-angular/progressbar';
149
import { IgxSnackbarComponent } from 'igniteui-angular/snackbar';
150
import { IgxIconComponent } from 'igniteui-angular/icon';
151
import { IgxPivotGridRow } from './pivot-grid-row';
152
import { IgxGridBaseDirective, IgxGridRowComponent } from 'igniteui-angular/grids/grid';
153

154
let NEXT_ID = 0;
3✔
155
const MINIMUM_COLUMN_WIDTH = 200;
3✔
156
const MINIMUM_COLUMN_WIDTH_SUPER_COMPACT = 104;
3✔
157

158
/* blazorAdditionalDependency: Column */
159
/* blazorAdditionalDependency: ColumnGroup */
160
/* blazorAdditionalDependency: ColumnLayout */
161
/* blazorAdditionalDependency: GridToolbar */
162
/* blazorAdditionalDependency: GridToolbarActions */
163
/* blazorAdditionalDependency: GridToolbarTitle */
164
/* blazorAdditionalDependency: GridToolbarAdvancedFiltering */
165
/* blazorAdditionalDependency: GridToolbarExporter */
166
/* blazorAdditionalDependency: GridToolbarHiding */
167
/* blazorAdditionalDependency: GridToolbarPinning */
168
/* blazorAdditionalDependency: ActionStrip */
169
/* blazorAdditionalDependency: GridActionsBaseDirective */
170
/* blazorAdditionalDependency: GridEditingActions */
171
/* blazorAdditionalDependency: GridPinningActions */
172
/* blazorAdditionalDependency: PivotDateDimension */
173
/* blazorIndirectRender */
174
/**
175
 * Pivot Grid provides a way to present and manipulate data in a pivot table view.
176
 *
177
 * @igxModule IgxPivotGridModule
178
 * @igxGroup Grids & Lists
179
 * @igxKeywords pivot, grid, table
180
 * @igxTheme igx-grid-theme
181
 * @remarks
182
 * The Ignite UI Pivot Grid is used for grouping and aggregating simple flat data into a pivot table.  Once data
183
 * has been bound and the dimensions and values configured it can be manipulated via sorting and filtering.
184
 * @example
185
 * ```html
186
 * <igx-pivot-grid [data]="data" [pivotConfiguration]="configuration">
187
 * </igx-pivot-grid>
188
 * ```
189
 */
190
@Component({
191
    changeDetection: ChangeDetectionStrategy.OnPush,
192
    preserveWhitespaces: false,
193
    selector: 'igx-pivot-grid',
194
    templateUrl: 'pivot-grid.component.html',
195
    encapsulation: ViewEncapsulation.None,
196
    providers: [
197
        IgxGridCRUDService,
198
        IgxGridValidationService,
199
        IgxGridSummaryService,
200
        IgxGridSelectionService,
201
        IgxColumnResizingService,
202
        GridBaseAPIService,
203
        { provide: IGX_GRID_SERVICE_BASE, useClass: GridBaseAPIService },
204
        { provide: IGX_GRID_BASE, useExisting: IgxPivotGridComponent },
205
        { provide: IgxFilteringService, useClass: IgxPivotFilteringService },
206
        IgxGridNavigationService,
207
        IgxPivotGridNavigationService,
208
        IgxPivotColumnResizingService,
209
        IgxForOfSyncService,
210
        IgxForOfScrollSyncService
211
    ],
212
    imports: [
213
        NgClass,
214
        NgStyle,
215
        NgTemplateOutlet,
216
        IgxPivotHeaderRowComponent,
217
        IgxGridBodyDirective,
218
        IgxGridDragSelectDirective,
219
        IgxColumnMovingDropDirective,
220
        IgxGridForOfDirective,
221
        IgxTemplateOutletDirective,
222
        IgxPivotRowComponent,
223
        IgxToggleDirective,
224
        IgxCircularProgressBarComponent,
225
        IgxSnackbarComponent,
226
        IgxOverlayOutletDirective,
227
        IgxPivotGridColumnResizerComponent,
228
        IgxIconComponent,
229
        IgxPivotRowDimensionContentComponent,
230
        IgxGridExcelStyleFilteringComponent,
231
        IgxExcelStyleColumnOperationsTemplateDirective,
232
        IgxExcelStyleFilterOperationsTemplateDirective,
233
        IgxExcelStyleSearchComponent,
234
        IgxGridRowClassesPipe,
235
        IgxGridRowStylesPipe,
236
        IgxPivotRowPipe,
237
        IgxPivotRowExpansionPipe,
238
        IgxPivotAutoTransform,
239
        IgxPivotColumnPipe,
240
        IgxPivotGridFilterPipe,
241
        IgxPivotGridSortingPipe,
242
        IgxPivotGridColumnSortingPipe,
243
        IgxPivotCellMergingPipe,
244
        IgxPivotGridHorizontalRowGrouping,
245
        IgxPivotRowDimensionMrlRowComponent
246
    ],
247
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
248
})
249
export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnInit, AfterContentInit,
3✔
250
    PivotGridType, AfterViewInit, OnChanges {
251
    /* blazorSuppress */
252
    public override readonly gridAPI = inject<GridBaseAPIService<IgxGridBaseDirective & GridType>>(GridBaseAPIService);
158✔
253
    /* blazorSuppress */
254
    public override navigation = inject(IgxPivotGridNavigationService);
158✔
255
    protected override colResizingService = inject(IgxPivotColumnResizingService);
158✔
256

257
    /**
258
     * Emitted when the dimension collection is changed via the grid chip area.
259
     *
260
     * @remarks
261
     * Returns the new dimension collection and its type:
262
     * @example
263
     * ```html
264
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
265
     *              (dimensionsChange)="dimensionsChange($event)"></igx-grid>
266
     * ```
267
     */
268
    @Output()
269
    public dimensionsChange = new EventEmitter<IDimensionsChange>();
158✔
270

271
    /**
272
     * Emitted when any of the pivotConfiguration properties is changed via the grid chip area.
273
     *
274
     * @example
275
     * ```html
276
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
277
     *              (pivotConfigurationChanged)="configurationChanged($event)"></igx-grid>
278
     * ```
279
     */
280
    @Output()
281
    public pivotConfigurationChange = new EventEmitter<IPivotConfigurationChangedEventArgs>();
158✔
282

283

284
    /**
285
     * Emitted when the dimension is initialized.
286
     * @remarks
287
     * Emits the dimension that is about to be initialized.
288
     * @example
289
     * ```html
290
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
291
     *              (dimensionInit)="dimensionInit($event)"></igx-pivot-grid>
292
     * ```
293
     */
294
    @Output()
295
    public dimensionInit = new EventEmitter<IPivotDimension>();
158✔
296

297
    /**
298
     * Emitted when the value is initialized.
299
     * @remarks
300
     * Emits the value that is about to be initialized.
301
     * @example
302
     * ```html
303
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
304
     *              (valueInit)="valueInit($event)"></igx-pivot-grid>
305
     * ```
306
     */
307
    @Output()
308
    public valueInit = new EventEmitter<IPivotValue>();
158✔
309

310

311
    /**
312
     * Emitted when a dimension is sorted.
313
     *
314
     * @example
315
     * ```html
316
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
317
     *              (dimensionsSortingExpressionsChange)="dimensionsSortingExpressionsChange($event)"></igx-pivot-grid>
318
     * ```
319
     */
320
    @Output()
321
    public dimensionsSortingExpressionsChange = new EventEmitter<ISortingExpression[]>();
158✔
322

323
    /**
324
     * Emitted when the values collection is changed via the grid chip area.
325
     *
326
     * @remarks
327
     * Returns the new dimension
328
     * @example
329
     * ```html
330
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
331
     *              (valuesChange)="valuesChange($event)"></igx-grid>
332
     * ```
333
    */
334
    @Output()
335
    public valuesChange = new EventEmitter<IValuesChange>();
158✔
336

337

338
    /**
339
     * Gets the sorting expressions generated for the dimensions.
340
     *
341
     * @example
342
     * ```typescript
343
     * const expressions = this.grid.dimensionsSortingExpressions;
344
     * ```
345
     */
346
    public get dimensionsSortingExpressions() {
347
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
24✔
348
        const dimensionsSortingExpressions = PivotSortUtil.generateDimensionSortingExpressions(allEnabledDimensions);
24✔
349
        return dimensionsSortingExpressions;
24✔
350
    }
351

352
    /** @hidden @internal */
353
    @ViewChild(IgxPivotHeaderRowComponent, { static: true })
354
    public override theadRow: IgxPivotHeaderRowComponent;
355

356
    /**
357
    * @hidden @internal
358
    */
359
    @ContentChild(IgxPivotValueChipTemplateDirective, { read: IgxPivotValueChipTemplateDirective })
360
    protected valueChipTemplateDirective: IgxPivotValueChipTemplateDirective;
361

362
    /**
363
     * @hidden @internal
364
     */
365
    @ContentChild(IgxPivotRowDimensionHeaderTemplateDirective, { read: IgxPivotRowDimensionHeaderTemplateDirective })
366
    protected rowDimensionHeaderDirective: IgxPivotRowDimensionHeaderTemplateDirective;
367

368
    /**
369
     * Gets/Sets a custom template for the value chips.
370
     *
371
     * @example
372
     * ```html
373
     * <igx-pivot-grid [valueChipTemplate]="myTemplate"><igx-pivot-grid>
374
     * ```
375
     */
376
    @Input()
377
    public valueChipTemplate: TemplateRef<IgxPivotGridValueTemplateContext>;
378

379
    @Input()
380
    public rowDimensionHeaderTemplate: TemplateRef<IgxColumnTemplateContext>;
381

382
    /* mustSetInCodePlatforms: WebComponents;Blazor;React */
383
    /* @tsTwoWayProperty (true, "PivotConfigurationChange", "Detail.PivotConfiguration", false) */
384
    /**
385
     * Gets/Sets the pivot configuration with all related dimensions and values.
386
     *
387
     * @example
388
     * ```html
389
     * <igx-pivot-grid [pivotConfiguration]="config"></igx-pivot-grid>
390
     * ```
391
     */
392
    @Input()
393
    public set pivotConfiguration(value: IPivotConfiguration) {
394
        this._pivotConfiguration = value;
183✔
395
        this.emitInitEvents(this._pivotConfiguration);
183✔
396
        this.filteringExpressionsTree = PivotUtil.buildExpressionTree(value);
183✔
397
        this.setDateDimensionsLocaleData();
183✔
398
        if (!this._init) {
183✔
399
            this.setupColumns();
23✔
400
        }
401
        this.notifyChanges(true);
183✔
402
    }
403

404
    /* mustSetInCodePlatforms: WebComponents;Blazor */
405
    public get pivotConfiguration() {
406
        return this._pivotConfiguration || { rows: null, columns: null, values: null, filters: null };
1,198,147✔
407
    }
408

409
    /**
410
     * Gets/Sets whether to auto-generate the pivot configuration based on the provided data.
411
     *
412
     * @remarks
413
     * The default value is false. When set to true, it will override all dimensions and values in the pivotConfiguration.
414
     * @example
415
     * ```html
416
     * <igx-pivot-grid [data]="Data" [autoGenerateConfig]="true"></igx-pivot-grid>
417
     * ```
418
     */
419
    @Input({ transform: booleanAttribute })
420
    public autoGenerateConfig = false;
158✔
421

422
    @Input()
423
    /**
424
     * Gets/Sets the pivot ui settings for the pivot grid - chips and their
425
     * corresponding containers for row, filter, column dimensions and values
426
     * as well as headers for the row dimensions values.
427
     * @example
428
     * ```html
429
     * <igx-pivot-grid [pivotUI]="{ showRowHeaders: true }"></igx-pivot-grid>
430
     * ```
431
     */
432
    public set pivotUI(value: IPivotUISettings) {
433
        this._pivotUI = Object.assign(this._pivotUI, value || {});
22!
434
        this.pipeTrigger++;
22✔
435
        this.notifyChanges(true);
22✔
436
    }
437

438
    public get pivotUI() {
439
        return this._pivotUI;
162,127✔
440
    }
441

442
    /**
443
     * @hidden @internal
444
     */
445
    @HostBinding('attr.role')
446
    public role = 'grid';
158✔
447

448
    /**
449
     * Enables a super compact theme for the component.
450
     * @remarks
451
     * Overrides the grid size option if one is set.
452
     * @example
453
     * ```html
454
     * <igx-pivot-grid [superCompactMode]="true"></igx-pivot-grid>
455
     * ```
456
     */
457
    @HostBinding('class.igx-grid__pivot--super-compact')
458
    @Input()
459
    public get superCompactMode() {
460
        return this._superCompactMode;
54,784✔
461
    }
462

463
    public set superCompactMode(value) {
464
        this._superCompactMode = value;
3✔
465
    }
466

467
    /** @hidden @internal */
468
    public override get gridSize() {
469
        if (this.superCompactMode) {
708✔
470
            return ɵSize.Small;
4✔
471
        }
472
        return super.gridSize;
704✔
473
    }
474

475

476
    /**
477
     * Gets/Sets the values clone strategy of the pivot grid when assigning them to different dimensions.
478
     *
479
     * @example
480
     * ```html
481
     *  <igx-pivot-grid #grid [data]="localData" [pivotValueCloneStrategy]="customCloneStrategy"></igx-pivot-grid>
482
     * ```
483
     * @hidden @internal
484
     */
485
    @Input()
486
    public get pivotValueCloneStrategy(): IDataCloneStrategy {
487
        return this._pivotValueCloneStrategy;
5,881✔
488
    }
489

490
    public set pivotValueCloneStrategy(strategy: IDataCloneStrategy) {
491
        if (strategy) {
×
492
            this._pivotValueCloneStrategy = strategy;
×
493
        }
494
    }
495

496
    /**
497
     * @hidden @internal
498
     */
499
    @ViewChild('record_template', { read: TemplateRef, static: true })
500
    public recordTemplate: TemplateRef<any>;
501

502
    /**
503
     * @hidden @internal
504
     */
505
    @ViewChild(IgxPivotRowDimensionMrlRowComponent, { read: IgxPivotRowDimensionMrlRowComponent })
506
    public rowDimensionMrlComponent: IgxPivotRowDimensionMrlRowComponent;
507

508
    /**
509
     * @hidden @internal
510
     */
511
    @ViewChild('headerTemplate', { read: TemplateRef, static: true })
512
    public headerTemplate: TemplateRef<any>;
513

514
    /**
515
     * @hidden @internal
516
     */
517
    @ViewChildren('rowDimensionContainer', { read: ElementRef })
518
    public rowDimensionContainer: QueryList<ElementRef<any>>;
519

520
    /**
521
     * @hidden @internal
522
     */
523
    @ViewChild(IgxPivotGridColumnResizerComponent)
524
    public override resizeLine: IgxPivotGridColumnResizerComponent;
525

526
    /**
527
     * @hidden @internal
528
     */
529
    @ViewChildren(IgxGridExcelStyleFilteringComponent, { read: IgxGridExcelStyleFilteringComponent })
530
    public override excelStyleFilteringComponents: QueryList<IgxGridExcelStyleFilteringComponent>;
531

532
    /**
533
     * @hidden @internal
534
     */
535
    @ViewChildren(IgxPivotRowDimensionContentComponent)
536
    protected rowDimensionContentCollection: QueryList<IgxPivotRowDimensionContentComponent>;
537

538
    /**
539
     * @hidden @internal
540
     */
541
    public override get minColumnWidth() {
542
        if (this.superCompactMode) {
53,048✔
543
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
31✔
544
        } else {
545
            return MINIMUM_COLUMN_WIDTH;
53,017✔
546
        }
547
    }
548

549
    /**
550
     * @hidden @internal
551
     */
552
    @ViewChildren('verticalRowDimScrollContainer', { read: IgxGridForOfDirective })
553
    public verticalRowDimScrollContainers: QueryList<IgxGridForOfDirective<any, any[]>>;
554

555
    /**
556
     * @hidden @internal
557
     */
558
    @ViewChildren(IgxPivotRowDimensionMrlRowComponent)
559
    public rowDimensionMrlRowsCollection: QueryList<IgxPivotRowDimensionMrlRowComponent>;
560

561
    /**
562
     * @hidden @internal
563
     */
564
    @Input()
565
    public override addRowEmptyTemplate: TemplateRef<void>;
566

567
    /**
568
     * @hidden @internal
569
     */
570
    @Input()
571
    public override autoGenerateExclude: string[] = [];
158✔
572

573
    /**
574
     * @hidden @internal
575
     */
576
    @Input()
577
    public override snackbarDisplayTime = 6000;
158✔
578

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

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

591
    /**
592
     * @hidden @internal
593
     */
594
    @Output()
595
    public override cellEditEnter = new EventEmitter<IGridEditEventArgs>();
158✔
596

597
    /**
598
     * @hidden @internal
599
     */
600
    @Output()
601
    public override cellEditExit = new EventEmitter<IGridEditDoneEventArgs>();
158✔
602

603
    /**
604
     * @hidden @internal
605
     */
606
    @Output()
607
    public override columnMovingStart = new EventEmitter<IColumnMovingStartEventArgs>();
158✔
608

609
    /**
610
     * @hidden @internal
611
     */
612
    @Output()
613
    public override columnMoving = new EventEmitter<IColumnMovingEventArgs>();
158✔
614

615
    /**
616
     * @hidden @internal
617
     */
618
    @Output()
619
    public override columnMovingEnd = new EventEmitter<IColumnMovingEndEventArgs>();
158✔
620

621
    /**
622
     * @hidden @internal
623
     */
624
    @Output()
625
    public override columnPin = new EventEmitter<IPinColumnCancellableEventArgs>();
158✔
626

627
    /**
628
     * @hidden @internal
629
     */
630
    @Output()
631
    public override columnPinned = new EventEmitter<IPinColumnEventArgs>();
158✔
632

633
    /**
634
     * @hidden @internal
635
     */
636
    @Output()
637
    public override rowAdd = new EventEmitter<IRowDataCancelableEventArgs>();
158✔
638

639
    /**
640
     * @hidden @internal
641
     */
642
    @Output()
643
    public override rowAdded = new EventEmitter<IRowDataEventArgs>();
158✔
644

645
    /**
646
     * @hidden @internal
647
     */
648
    @Output()
649
    public override rowDeleted = new EventEmitter<IRowDataEventArgs>();
158✔
650

651
    /**
652
     * @hidden @internal
653
     */
654
    @Output()
655
    public override rowDelete = new EventEmitter<IRowDataCancelableEventArgs>();
158✔
656

657
    /**
658
     * @hidden @internal
659
     */
660
    @Output()
661
    public override rowDragStart = new EventEmitter<IRowDragStartEventArgs>();
158✔
662

663
    /**
664
     * @hidden @internal
665
     */
666
    @Output()
667
    public override rowDragEnd = new EventEmitter<IRowDragEndEventArgs>();
158✔
668

669
    /**
670
     * @hidden @internal
671
     */
672
    @Output()
673
    public override rowEditEnter = new EventEmitter<IGridEditEventArgs>();
158✔
674

675
    /**
676
     * @hidden @internal
677
     */
678
    @Output()
679
    public override rowEdit = new EventEmitter<IGridEditEventArgs>();
158✔
680

681
    /**
682
     * @hidden @internal
683
     */
684
    @Output()
685
    public override rowEditDone = new EventEmitter<IGridEditDoneEventArgs>();
158✔
686

687
    /**
688
     * @hidden @internal
689
     */
690
    @Output()
691
    public override rowEditExit = new EventEmitter<IGridEditDoneEventArgs>();
158✔
692

693
    /**
694
     * @hidden @internal
695
     */
696
    @Output()
697
    public override rowPinning = new EventEmitter<IPinRowEventArgs>();
158✔
698

699
    /**
700
     * @hidden @internal
701
     */
702
    @Output()
703
    public override rowPinned = new EventEmitter<IPinRowEventArgs>();
158✔
704

705
    /** @hidden @internal */
706
    public columnGroupStates = new Map<string, boolean>();
158✔
707
    /** @hidden @internal */
708
    public dimensionDataColumns: any[];
709
    /** @hidden @internal */
710
    public get pivotKeys() {
711
        return this.pivotConfiguration.pivotKeys || DEFAULT_PIVOT_KEYS;
216,144✔
712
    }
713
    /** @hidden @internal */
714
    public override get type(): GridType["type"] {
715
        return 'pivot';
6,739✔
716
    }
717

718
    /**
719
     * @hidden @internal
720
     */
721
    public override dragRowID = null;
158✔
722

723
    /**
724
    * @hidden @internal
725
    */
726
    public override get rootSummariesEnabled(): boolean {
727
        return false;
6,384✔
728
    }
729

730
    /**
731
     * @hidden @internal
732
     */
733
    public rowDimensionResizing = true;
158✔
734

735
    private _emptyRowDimension: IPivotDimension = { memberName: '', enabled: true, level: 0 };
158✔
736
    /**
737
     * @hidden @internal
738
     */
739
    public get emptyRowDimension(): IPivotDimension {
740
        return this._emptyRowDimension;
3,737✔
741
    }
742

743
    protected _pivotValueCloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy();
158✔
744
    protected override _defaultExpandState = false;
158✔
745
    protected override _filterStrategy: IFilteringStrategy = new DimensionValuesFilteringStrategy();
158✔
746
    protected regroupTrigger = 0;
158✔
747
    private _data;
748
    private _pivotConfiguration: IPivotConfiguration = { rows: null, columns: null, values: null, filters: null };
158✔
749
    private p_id = `igx-pivot-grid-${NEXT_ID++}`;
158✔
750
    private _superCompactMode = false;
158✔
751
    private _pivotUI: IPivotUISettings = {
158✔
752
        showConfiguration: true,
753
        showRowHeaders: false,
754
        rowLayout: PivotRowLayoutType.Vertical,
755
        horizontalSummariesPosition: PivotSummaryPosition.Bottom
756
    };
757
    private _sortableColumns = true;
158✔
758
    private _visibleRowDimensions: IPivotDimension[] = [];
158✔
759
    private _shouldUpdateSizes = false;
158✔
760

761
    /**
762
    * Gets/Sets the default expand state for all rows.
763
    */
764
    @Input({ transform: booleanAttribute })
765
    public get defaultExpandState() {
766
        return this._defaultExpandState;
2,800✔
767
    }
768

769
    public set defaultExpandState(val: boolean) {
770
        this._defaultExpandState = val;
148✔
771
    }
772

773
    /**
774
     * @hidden @internal
775
     */
776
    @Input()
777
    public override get pagingMode(): GridPagingMode {
778
        return 'local';
×
779
    }
780

781
    public override set pagingMode(_val: GridPagingMode) {
782
    }
783

784
    /**
785
     * @hidden @internal
786
     */
787
    @WatchChanges()
788
    @Input({ transform: booleanAttribute })
789
    public override get hideRowSelectors(): boolean {
790
        return false;
×
791
    }
792

793
    public override set hideRowSelectors(_value: boolean) {
794
    }
795

796
    /**
797
     * @hidden @internal
798
     */
799
    public override autoGenerate = true;
158✔
800

801
    /**
802
     * @hidden @internal
803
     */
804
    public override get actionStrip() {
805
        return undefined as any;
1,158✔
806
    }
807

808
    /**
809
     * @hidden @internal
810
     * @deprecated in version 18.2.0. This property is no longer supported.
811
     */
812
    public override get shouldGenerate(): boolean {
813
        return false;
×
814
    }
815

816
    public override set shouldGenerate(value: boolean) {
817
    }
818

819
    /**
820
     * @hidden @internal
821
     */
822
    public override moving = false;
158✔
823

824
    /**
825
     * @hidden @internal
826
     */
827
    public override toolbarExporting = new EventEmitter<IGridToolbarExportEventArgs>();
158✔
828

829
    /**
830
     * @hidden @internal
831
     */
832
    @Input({ transform: booleanAttribute })
833
    public override get rowDraggable(): boolean {
834
        return false;
×
835
    }
836

837

838
    public override set rowDraggable(_val: boolean) {
839
    }
840

841
    /**
842
     * @hidden @internal
843
     */
844
    @Input({ transform: booleanAttribute })
845
    public override get allowAdvancedFiltering() {
846
        return false;
×
847
    }
848

849
    public override set allowAdvancedFiltering(_value) {
850
    }
851

852
    /**
853
     * @hidden @internal
854
     */
855
    @Input()
856
    public override get filterMode() {
857
        return FilterMode.quickFilter;
×
858
    }
859

860
    public override set filterMode(_value: FilterMode) {
861
    }
862

863
    /**
864
     * @hidden @internal
865
     */
866
    @Input({ transform: booleanAttribute })
867
    public override get allowFiltering() {
868
        return false;
48,752✔
869
    }
870

871
    public override set allowFiltering(_value) {
872
    }
873

874
    /**
875
     * @hidden @internal
876
     */
877
    @Input()
878
    public override get page(): number {
879
        return 0;
×
880
    }
881

882
    public override set page(_val: number) {
883
    }
884

885
    /**
886
     * @hidden @internal
887
     */
888
    @Input()
889
    public override get perPage(): number {
890
        return 0;
×
891
    }
892

893
    public override set perPage(_val: number) {
894
    }
895

896
    /**
897
     * @hidden @internal
898
     */
899
    public override get pinnedColumns(): IgxColumnComponent[] {
900
        return [];
13✔
901
    }
902

903
    /**
904
    * @hidden @internal
905
    */
906
    public override get unpinnedColumns(): IgxColumnComponent[] {
907
        return super.unpinnedColumns;
34,616✔
908
    }
909

910
    /**
911
    * @hidden @internal
912
    */
913
    public override get unpinnedDataView(): any[] {
914
        return super.unpinnedDataView;
×
915
    }
916

917
    /**
918
    * @hidden @internal
919
    */
920
    public override get unpinnedWidth() {
921
        return super.unpinnedWidth;
31,036✔
922
    }
923

924
    /**
925
     * @hidden @internal
926
     */
927
    public override get pinnedStartWidth() {
928
        return super.pinnedStartWidth;
3,380✔
929
    }
930

931
    /**
932
     * @hidden @internal
933
     */
934
    @Input()
935
    public override set summaryRowHeight(_value: number) {
936
    }
937

938
    public override get summaryRowHeight(): number {
939
        return 0;
682✔
940
    }
941

942
    /**
943
     * @hidden @internal
944
     */
945
    public override get transactions(): TransactionService<Transaction, State> {
946
        return this._transactions;
254,848✔
947
    }
948

949

950

951
    /**
952
     * @hidden @internal
953
     */
954
    public override get dragIndicatorIconTemplate(): TemplateRef<any> {
955
        return;
×
956
    }
957

958
    public override set dragIndicatorIconTemplate(_val: TemplateRef<any>) {
959
    }
960

961
    /**
962
     * @hidden @internal
963
     */
964
    @WatchChanges()
965
    @Input({ transform: booleanAttribute })
966
    public override get rowEditable(): boolean {
967
        return;
297,913✔
968
    }
969

970
    public override set rowEditable(_val: boolean) {
971
    }
972

973
    /**
974
     * @hidden @internal
975
     */
976
    @Input()
977
    public override get pinning() {
978
        return {};
198,525✔
979
    }
980
    public override set pinning(_value) {
981
    }
982

983
    /**
984
     * @hidden @internal
985
     */
986
    @Input()
987
    public override get summaryPosition() {
988
        return;
×
989
    }
990

991
    public override set summaryPosition(_value: GridSummaryPosition) {
992
    }
993

994
    /**
995
     * @hidden @internal
996
     */
997
    @Input()
998
    public override get summaryCalculationMode() {
999
        return;
×
1000
    }
1001

1002
    public override set summaryCalculationMode(_value: GridSummaryCalculationMode) {
1003
    }
1004

1005
    /**
1006
     * @hidden @internal
1007
     */
1008
    @Input({ transform: booleanAttribute })
1009
    public override get showSummaryOnCollapse() {
1010
        return;
×
1011
    }
1012

1013
    public override set showSummaryOnCollapse(_value: boolean) {
1014
    }
1015

1016
    /**
1017
     * @hidden @internal
1018
     */
1019
    public override get hiddenColumnsCount(): number {
1020
        return 0;
×
1021
    }
1022

1023
    /**
1024
     * @hidden @internal
1025
     */
1026
    public override get pinnedColumnsCount(): number {
1027
        return 0;
×
1028
    }
1029

1030
    /**
1031
     * @hidden @internal
1032
     */
1033
    @Input({ transform: booleanAttribute })
1034
    public override get batchEditing(): boolean {
1035
        return false;
×
1036
    }
1037

1038
    public override set batchEditing(_val: boolean) {
1039
    }
1040

1041
    /* csSuppress */
1042
    public override get selectedRows(): any[] {
1043
        if (this.selectionService.getSelectedRows().length === 0) {
19✔
1044
            return [];
4✔
1045
        }
1046
        const selectedRowIds = [];
15✔
1047
        this.dataView.forEach(record => {
15✔
1048
            const prev = [];
182✔
1049
            for (const dim of this.rowDimensions) {
182✔
1050
                let currDim = dim;
345✔
1051
                let shouldBreak = false;
345✔
1052
                do {
345✔
1053
                    const key = PivotUtil.getRecordKey(record, currDim);
651✔
1054
                    if (this.selectionService.isPivotRowSelected(key) && !selectedRowIds.find(x => x === record)) {
651✔
1055
                        selectedRowIds.push(record);
29✔
1056
                        shouldBreak = true;
29✔
1057
                        break;
29✔
1058
                    }
1059
                    currDim = currDim.childLevel;
622✔
1060
                } while (currDim);
1061
                prev.push(dim);
345✔
1062
                if (shouldBreak) {
345✔
1063
                    break;
29✔
1064
                }
1065
            }
1066

1067
        });
1068

1069
        return selectedRowIds;
15✔
1070
    }
1071

1072
    /**
1073
     * @hidden
1074
     */
1075
    public override ngOnInit() {
1076
        // pivot grid always generates columns automatically.
1077
        this.autoGenerate = true;
158✔
1078
        super.ngOnInit();
158✔
1079
    }
1080

1081
    /**
1082
     * @hidden
1083
     */
1084
    public override ngAfterContentInit() {
1085
        // ignore any user defined columns and auto-generate based on pivot config.
1086
        this.updateColumns([]);
158✔
1087
        Promise.resolve().then(() => {
158✔
1088
            if (this.autoGenerateConfig) {
158!
1089
                this.generateConfig();
×
1090
            }
1091
            this.setupColumns();
158✔
1092
            // Bind to onResourceChange after the columns have initialized the first time to avoid premature initialization.
1093
            onResourceChangeHandle(this.destroy$, () => {
158✔
1094
                this.setDateDimensionsLocaleData();
1✔
1095
                // Since the columns are kinda static, due to assigning DisplayName on init, they need to be regenerated.
1096
                Promise.resolve().then(() => {
1✔
1097
                    this.setupColumns();
1✔
1098
                });
1099
            }, this);
1100
        });
1101
        if (this.valueChipTemplateDirective) {
158!
1102
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
×
1103
        }
1104
        if (this.rowDimensionHeaderDirective) {
158!
1105
            this.rowDimensionHeaderTemplate = this.rowDimensionHeaderDirective.template;
×
1106
        }
1107
    }
1108

1109
    /**
1110
     * @hidden @internal
1111
     */
1112
    public override ngAfterViewInit() {
1113
        Promise.resolve().then(() => {
158✔
1114
            super.ngAfterViewInit();
158✔
1115
        });
1116

1117
    }
1118

1119
    /**
1120
     * @hidden @internal
1121
     */
1122
    public ngOnChanges(changes: SimpleChanges) {
1123
        if (changes.superCompactMode && !changes.superCompactMode.isFirstChange()) {
209!
1124
            this._shouldUpdateSizes = true;
×
1125
            resizeObservable(this.verticalScrollContainer.displayContainer).pipe(take(1), takeUntil(this.destroy$)).subscribe(() => this.resizeNotify.next());
×
1126
        }
1127
    }
1128

1129
    /**
1130
     * Notifies for dimension change.
1131
     */
1132
    public notifyDimensionChange(regenerateColumns = false) {
×
1133
        if (regenerateColumns) {
19✔
1134
            this.setupColumns();
19✔
1135
        }
1136
        this.pipeTrigger++;
19✔
1137
        this.cdr.detectChanges();
19✔
1138
    }
1139

1140
    /**
1141
     * Gets the full list of dimensions.
1142
     *
1143
     * @example
1144
     * ```typescript
1145
     * const dimensions = this.grid.allDimensions;
1146
     * ```
1147
     */
1148
    public get allDimensions() {
1149
        const config = this._pivotConfiguration;
1,123✔
1150
        if (!config) return [];
1,123✔
1151
        return (config.rows || []).concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
2,687!
1152
    }
1153

1154
    protected get allVisibleDimensions() {
1155
        const config = this._pivotConfiguration;
310✔
1156
        if (!config) return [];
310✔
1157
        const uniqueVisibleRowDims = this.visibleRowDimensions.filter(dim => !config.rows.find(configRow => configRow.memberName === dim.memberName));
338✔
1158
        const rows = (config.rows || []).concat(...uniqueVisibleRowDims);
306!
1159
        return rows.concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
890!
1160
    }
1161

1162
    protected override get shouldResize(): boolean {
1163
        if (!this.dataRowList.first?.cells || this.dataRowList.first.cells.length === 0) {
146!
1164
            return false;
×
1165
        }
1166
        const isSizePropChanged = super.shouldResize;
146✔
1167
        if (isSizePropChanged || this._shouldUpdateSizes) {
146✔
1168
            this._shouldUpdateSizes = false;
60✔
1169
            return true;
60✔
1170
        }
1171
        return false;
86✔
1172
    }
1173

1174
    protected get emptyBottomSize() {
1175
        return this.totalHeight - (<any>this.verticalScroll).scrollComponent.size;
7,078✔
1176
    }
1177

1178
    /** @hidden @internal */
1179
    public createFilterESF(dropdown: any, column: ColumnType, options: OverlaySettings, shouldReatach: boolean) {
1180
        options.outlet = this.outlet;
5✔
1181
        if (dropdown) {
5✔
1182
            dropdown.initialize(column, this.overlayService);
5✔
1183
            dropdown.populateData();
5✔
1184
            if (shouldReatach) {
5✔
1185
                const id = this.overlayService.attach(dropdown.element, options);
3✔
1186
                dropdown.overlayComponentId = id;
3✔
1187
                return { id, ref: undefined };
3✔
1188
            }
1189
            return { id: dropdown.overlayComponentId, ref: undefined };
2✔
1190
        }
1191
    }
1192

1193
    /** @hidden */
1194
    public override featureColumnsWidth() {
1195
        return this.pivotRowWidths || 0;
10,212✔
1196
    }
1197

1198
    /* blazorSuppress */
1199
    /**
1200
     * Gets/Sets the value of the `id` attribute.
1201
     *
1202
     * @remarks
1203
     * If not provided it will be automatically generated.
1204
     * @example
1205
     * ```html
1206
     * <igx-pivot-grid [id]="'igx-pivot-1'" [data]="Data"></igx-pivot-grid>
1207
     * ```
1208
     */
1209
    @HostBinding('attr.id')
1210
    @Input()
1211
    public get id(): string {
1212
        return this.p_id;
86,286✔
1213
    }
1214
    /* blazorSuppress */
1215
    public set id(value: string) {
1216
        this.p_id = value;
×
1217
    }
1218

1219
    /* treatAsRef */
1220
    /* blazorAlternateType: object */
1221
    /**
1222
     * Gets/Sets the array of data that populates the component.
1223
     * ```html
1224
     * <igx-pivot-grid [data]="Data"></igx-pivot-grid>
1225
     * ```
1226
     */
1227
    @Input()
1228
    public set data(value: any[] | null) {
1229
        this._data = value || [];
168!
1230
        if (!this._init) {
168✔
1231
            if (this.autoGenerateConfig) {
9✔
1232
                this.generateConfig();
1✔
1233
            }
1234
            this.setupColumns();
9✔
1235
            this.reflow();
9✔
1236
        }
1237
        this.cdr.markForCheck();
168✔
1238
        if (this.height === null || this.height.indexOf('%') !== -1) {
168✔
1239
            // If the height will change based on how much data there is, recalculate sizes in igxForOf.
1240
            this.notifyChanges(true);
79✔
1241
        }
1242
    }
1243

1244
    /* treatAsRef */
1245
    /* blazorAlternateType: object */
1246
    /**
1247
     * Returns an array of data set to the component.
1248
     * ```typescript
1249
     * let data = this.grid.data;
1250
     * ```
1251
     */
1252
    public get data(): any[] | null {
1253
        return this._data;
90,200✔
1254
    }
1255

1256
    /**
1257
     * @hidden
1258
     */
1259
    public getContext(rowData, rowIndex): any {
1260
        return {
14,975✔
1261
            $implicit: rowData,
1262
            templateID: {
1263
                type: 'dataRow',
1264
                id: null
1265
            },
1266
            index: this.getDataViewIndex(rowIndex, false)
1267
        };
1268
    }
1269

1270
    /**
1271
     * @hidden @internal
1272
     */
1273
    public get pivotRowWidths() {
1274
        return this.visibleRowDimensions.length ? this.visibleRowDimensions.reduce((accumulator, dim) => accumulator + this.rowDimensionWidthToPixels(dim), 0) :
28,492✔
1275
            this.rowDimensionWidthToPixels(this.emptyRowDimension);
1276
    }
1277

1278
    /**
1279
     * @hidden @internal
1280
     */
1281
    public rowDimensionWidth(dim): string {
1282
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
44,267✔
1283
        if (isAuto) {
44,267✔
1284
            return dim.autoWidth ? dim.autoWidth + 'px' : 'fit-content';
121!
1285
        } else {
1286
            return this.rowDimensionWidthToPixels(dim) + 'px';
44,146✔
1287
        }
1288
    }
1289

1290
    /**
1291
     * @hidden @internal
1292
     */
1293
    public rowDimensionWidthToPixels(dim: IPivotDimension): number {
1294
        if (!dim?.width) {
115,100✔
1295
            return MINIMUM_COLUMN_WIDTH;
110,949✔
1296
        }
1297
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
4,151✔
1298
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
4,151✔
1299
        if (isPercent) {
4,151✔
1300
            return Math.round(parseFloat(dim.width) / 100 * this.calcWidth);
782✔
1301
        } else if (isAuto) {
3,369✔
1302
            return dim.autoWidth;
150✔
1303
        } else {
1304
            return parseInt(dim.width, 10);
3,219✔
1305
        }
1306
    }
1307

1308
    /**
1309
     * @hidden @internal
1310
     */
1311
    public reverseDimensionWidthToPercent(width: number): number {
1312
        return (width * 100 / this.calcWidth);
1✔
1313
    }
1314

1315
    /** @hidden @internal */
1316
    public get pivotContentCalcWidth() {
1317
        if (!this.platform.isBrowser) {
2,800!
1318
            return undefined;
×
1319
        }
1320
        if (!this.visibleRowDimensions.length) {
2,800✔
1321
            return Math.max(0, this.calcWidth - this.pivotRowWidths);
264✔
1322
        }
1323

1324
        const totalDimWidth = this.visibleRowDimensions.length > 0 ?
2,536!
1325
            this.visibleRowDimensions.map((dim) => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur) :
4,333✔
1326
            0;
1327
        return this.calcWidth - totalDimWidth;
2,536✔
1328
    }
1329

1330
    /** @hidden @internal */
1331
    public get pivotPinnedStartWidth() {
1332
        return !this._init ? this.pinnedStartWidth : 0;
5,600✔
1333
    }
1334

1335
    /** @hidden @internal */
1336
    public get pivotPinnedEndWidth() {
1337
        return !this._init ? this.pinnedEndWidth : 0;
8,400✔
1338
    }
1339

1340
    /** @hidden @internal */
1341
    public get pivotUnpinnedWidth() {
1342
        return this.unpinnedWidth || 0;
2,800!
1343
    }
1344

1345
    /** @hidden @internal */
1346
    public get rowDimensions() {
1347
        return this.pivotConfiguration.rows?.filter(x => x.enabled) || [];
108,680✔
1348
    }
1349

1350
    /** @hidden @internal */
1351
    public set visibleRowDimensions(value: IPivotDimension[]) {
1352
        this._visibleRowDimensions = value;
900✔
1353
    }
1354

1355
    public get visibleRowDimensions() {
1356
        return this._visibleRowDimensions || this.rowDimensions;
51,799!
1357
    }
1358

1359
    /** @hidden @internal */
1360
    public get columnDimensions() {
1361
        return this.pivotConfiguration.columns?.filter(x => x.enabled) || [];
397,142✔
1362
    }
1363

1364
    /** @hidden @internal */
1365
    public get filterDimensions() {
1366
        return this.pivotConfiguration.filters?.filter(x => x.enabled) || [];
7,612✔
1367
    }
1368

1369
    /** @hidden @internal */
1370
    public get values() {
1371
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
900,715✔
1372
    }
1373

1374
    public toggleColumn(col: IgxColumnComponent) {
1375
        const state = this.columnGroupStates.get(col.field);
4✔
1376
        const newState = !state;
4✔
1377
        this.columnGroupStates.set(col.field, newState);
4✔
1378
        this.toggleRowGroup(col, newState);
4✔
1379
        this.reflow();
4✔
1380
    }
1381

1382
    /**
1383
     * @hidden @internal
1384
     */
1385
    public override isRecordPinnedByIndex(_rowIndex: number) {
1386
        return false;
×
1387
    }
1388

1389
    /**
1390
     * @hidden @internal
1391
     */
1392
    public override toggleColumnVisibility(_args: IColumnVisibilityChangedEventArgs) {
1393
        return;
×
1394
    }
1395

1396
    /**
1397
     * @hidden @internal
1398
     */
1399
    public override expandAll() {
1400
    }
1401

1402
    /**
1403
     * @hidden @internal
1404
     */
1405
    public override collapseAll() {
1406
    }
1407

1408
    /**
1409
     * @hidden @internal
1410
     */
1411
    public override expandRow(_rowID: any) {
1412
    }
1413

1414
    /**
1415
     * @hidden @internal
1416
     */
1417
    public override collapseRow(_rowID: any) {
1418
    }
1419

1420
    /**
1421
     * @hidden @internal
1422
     */
1423
    public override get pinnedRows(): IgxGridRowComponent[] {
1424
        return;
2✔
1425
    }
1426

1427
    /**
1428
     * @hidden @internal
1429
     */
1430
    @Input()
1431
    public override get totalRecords(): number {
1432
        return;
×
1433
    }
1434

1435
    public override set totalRecords(_total: number) {
1436
    }
1437

1438
    /**
1439
     * @hidden @internal
1440
     */
1441
    public override moveColumn(_column: IgxColumnComponent, _target: IgxColumnComponent, _pos: DropPosition = DropPosition.AfterDropTarget) {
×
1442
    }
1443

1444
    /**
1445
     * @hidden @internal
1446
     */
1447
    public override addRow(_data: any): void {
1448
    }
1449

1450
    /**
1451
     * @hidden @internal
1452
     */
1453
    public override deleteRow(_rowSelector: any): any {
1454
    }
1455

1456
    /**
1457
     * @hidden @internal
1458
     */
1459
    public override updateCell(_value: any, _rowSelector: any, _column: string): void {
1460
    }
1461

1462
    /**
1463
     * @hidden @internal
1464
     */
1465
    public override updateRow(_value: any, _rowSelector: any): void {
1466
    }
1467

1468
    /**
1469
     * @hidden @internal
1470
     */
1471
    public override enableSummaries(..._rest) {
1472
    }
1473

1474
    /**
1475
     * @hidden @internal
1476
     */
1477
    public override disableSummaries(..._rest) {
1478
    }
1479

1480
    /**
1481
     * @hidden @internal
1482
     */
1483
    public override pinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
1484
        return;
×
1485
    }
1486

1487
    /**
1488
     * @hidden @internal
1489
     */
1490
    public override unpinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
1491
        return;
×
1492
    }
1493

1494
    /**
1495
     * @hidden @internal
1496
     */
1497
    public override pinRow(_rowID: any, _index?: number, _row?: RowType): boolean {
1498
        return;
×
1499
    }
1500

1501
    /**
1502
     * @hidden @internal
1503
     */
1504
    public override unpinRow(_rowID: any, _row?: RowType): boolean {
1505
        return;
×
1506
    }
1507

1508
    /**
1509
     * @hidden @internal
1510
     */
1511
    public override get pinnedRowHeight() {
1512
        return;
3,482✔
1513
    }
1514

1515
    /**
1516
     * @hidden @internal
1517
     */
1518
    public override get hasEditableColumns(): boolean {
1519
        return;
×
1520
    }
1521

1522
    /**
1523
     * @hidden @internal
1524
     */
1525
    public override get hasSummarizedColumns(): boolean {
1526
        return;
5✔
1527
    }
1528

1529
    /**
1530
     * @hidden @internal
1531
     */
1532
    public override get hasMovableColumns(): boolean {
1533
        return;
55,872✔
1534
    }
1535

1536
    /**
1537
     * @hidden @internal
1538
     */
1539
    public override get pinnedDataView(): any[] {
1540
        return [];
14,975✔
1541
    }
1542

1543
    /**
1544
     * @hidden @internal
1545
     */
1546
    public override openAdvancedFilteringDialog(_overlaySettings?: OverlaySettings) {
1547
    }
1548

1549
    /**
1550
     * @hidden @internal
1551
     */
1552
    public override closeAdvancedFilteringDialog(_applyChanges: boolean) {
1553
    }
1554

1555
    /**
1556
     * @hidden @internal
1557
     */
1558
    public override endEdit(_commit = true, _event?: Event): boolean {
×
1559
        return;
×
1560
    }
1561

1562
    /**
1563
     * @hidden @internal
1564
     */
1565
    public override beginAddRowById(_rowID: any, _asChild?: boolean): void {
1566
    }
1567

1568
    /**
1569
     * @hidden @internal
1570
     */
1571
    public override beginAddRowByIndex(_index: number): void {
1572
    }
1573

1574
    /**
1575
     * @hidden @internal
1576
     */
1577
    public override clearSearch() { }
1578

1579
    /**
1580
    * @hidden @internal
1581
    */
1582
    public override refreshSearch(_updateActiveInfo?: boolean, _endEdit = true): number {
120✔
1583
        return 0;
1,020✔
1584
    }
1585

1586
    /**
1587
    * @hidden @internal
1588
    */
1589
    public override findNext(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
1590
        return 0;
×
1591
    }
1592

1593
    /**
1594
    * @hidden @internal
1595
    */
1596
    public override findPrev(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
1597
        return 0;
×
1598
    }
1599

1600
    /**
1601
    * @hidden @internal
1602
    */
1603
    public override getNextCell(currRowIndex: number, curVisibleColIndex: number,
1604
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
×
1605
        return super.getNextCell(currRowIndex, curVisibleColIndex, callback);
×
1606
    }
1607

1608
    /**
1609
    * @hidden @internal
1610
    */
1611
    public override getPreviousCell(currRowIndex: number, curVisibleColIndex: number,
1612
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
×
1613
        return super.getPreviousCell(currRowIndex, curVisibleColIndex, callback);
×
1614
    }
1615

1616
    /**
1617
    * @hidden @internal
1618
    */
1619
    public override getPinnedStartWidth(takeHidden = false) {
724✔
1620
        return super.getPinnedStartWidth(takeHidden);
3,365✔
1621
    }
1622

1623
    /**
1624
     * @hidden @internal
1625
     */
1626
    public override get totalHeight() {
1627
        return this.calcHeight;
13,957✔
1628
    }
1629

1630
    public getColumnGroupExpandState(col: IgxColumnComponent) {
1631
        const state = this.columnGroupStates.get(col.field);
202✔
1632
        // columns are expanded by default?
1633
        return state !== undefined && state !== null ? state : false;
202✔
1634
    }
1635

1636
    public toggleRowGroup(col: IgxColumnComponent, newState: boolean) {
1637
        if (!col) return;
5!
1638
        if (this.hasMultipleValues) {
5✔
1639
            const parentCols = col.parent ? col.parent.children.toArray() : this._autoGeneratedCols.filter(x => x.level === 0);
88!
1640
            const siblingCol = parentCols.filter(x => x.header === col.header && x !== col)[0];
8✔
1641
            const currIndex = parentCols.indexOf(col);
4✔
1642
            const siblingIndex = parentCols.indexOf(siblingCol);
4✔
1643
            if (currIndex < siblingIndex) {
4✔
1644
                // clicked on the full hierarchy header
1645
                this.resolveToggle(col, newState);
3✔
1646
                siblingCol.headerTemplate = this.headerTemplate;
3✔
1647
            } else {
1648
                // clicked on summary parent column that contains just the measures
1649
                col.headerTemplate = undefined;
1✔
1650
                this.resolveToggle(siblingCol, newState);
1✔
1651
            }
1652
        } else {
1653
            const parentCols = col.parent ? col.parent.children : this._autoGeneratedCols.filter(x => x.level === 0);
5!
1654
            const fieldColumn = parentCols.filter(x => x.header === col.header && !x.columnGroup)[0];
2✔
1655
            const groupColumn = parentCols.filter(x => x.header === col.header && x.columnGroup)[0];
2✔
1656
            this.resolveToggle(groupColumn, newState);
1✔
1657
            if (newState) {
1!
1658
                fieldColumn.headerTemplate = this.headerTemplate;
1✔
1659
            } else {
1660
                fieldColumn.headerTemplate = undefined;
×
1661
            }
1662
        }
1663
    }
1664

1665
    /**
1666
    * @hidden @internal
1667
    */
1668
    public override setupColumns() {
1669
        super.setupColumns();
276✔
1670
    }
1671

1672
    /**
1673
    * @hidden @internal
1674
    */
1675
    public override dataRebinding(event: IForOfDataChangeEventArgs) {
1676
        if (this.hasHorizontalLayout) {
861✔
1677
            this.dimensionDataColumns = this.generateDimensionColumns();
31✔
1678
        }
1679

1680
        super.dataRebinding(event);
861✔
1681
    }
1682

1683
    /**
1684
     * Auto-sizes row dimension cells.
1685
     *
1686
     * @remarks
1687
     * Only sizes based on the dimension cells in view.
1688
     * @example
1689
     * ```typescript
1690
     * this.grid.autoSizeRowDimension(dimension);
1691
     * ```
1692
     * @param dimension The row dimension to size.
1693
     */
1694
    public autoSizeRowDimension(dimension: IPivotDimension) {
1695
        if (this.getDimensionType(dimension) === PivotDimensionType.Row) {
2✔
1696
            const relatedDims: string[] = PivotUtil.flatten([dimension]).map((x: IPivotDimension) => x.memberName);
4✔
1697
            const contentCollection = this.getContentCollection(dimension);
2✔
1698
            const content = contentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
20✔
1699
            const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
10✔
1700
            if (this.pivotUI.showRowHeaders) {
2!
1701
                const dimensionHeader = this.theadRow.rowDimensionHeaders.find(x => x.column.field === dimension.memberName);
×
1702
                headers.push(dimensionHeader);
×
1703
            }
1704
            const autoWidth = this.getLargesContentWidth(headers);
2✔
1705
            if (dimension.width === "auto") {
2!
1706
                dimension.autoWidth = parseFloat(autoWidth);
×
1707
            } else {
1708
                dimension.width = autoWidth;
2✔
1709
            }
1710
            this.pipeTrigger++;
2✔
1711
            this.cdr.detectChanges();
2✔
1712
        }
1713
    }
1714

1715
    /**
1716
     * Inserts dimension in target collection by type at specified index or at the collection's end.
1717
     *
1718
     * @example
1719
     * ```typescript
1720
     * this.grid.insertDimensionAt(dimension, PivotDimensionType.Row, 1);
1721
     * ```
1722
     * @param dimension The dimension that will be added.
1723
     * @param targetCollectionType The target collection type to add to. Can be Row, Column or Filter.
1724
     * @param index The index in the collection at which to add.
1725
     * This parameter is optional. If not set it will add it to the end of the collection.
1726
     */
1727
    public insertDimensionAt(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1728
        this.setDateDimensionsLocaleData([dimension]);
12✔
1729
        const targetCollection = this.getDimensionsByType(targetCollectionType);
12✔
1730
        if (index !== undefined) {
12✔
1731
            targetCollection.splice(index, 0, dimension);
11✔
1732
        } else {
1733
            targetCollection.push(dimension);
1✔
1734
        }
1735
        if (targetCollectionType === PivotDimensionType.Column) {
12✔
1736
            this.setupColumns();
4✔
1737
        }
1738
        this.pipeTrigger++;
12✔
1739
        this.dimensionsChange.emit({ dimensions: targetCollection, dimensionCollectionType: targetCollectionType });
12✔
1740
        if (targetCollectionType === PivotDimensionType.Filter) {
12✔
1741
            this.dimensionDataColumns = this.generateDimensionColumns();
3✔
1742
            this.reflow();
3✔
1743
        }
1744
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
12✔
1745
    }
1746

1747
    /**
1748
     * Move dimension from its currently collection to the specified target collection by type at specified index or at the collection's end.
1749
     *
1750
     * @example
1751
     * ```typescript
1752
     * this.grid.moveDimension(dimension, PivotDimensionType.Row, 1);
1753
     * ```
1754
     * @param dimension The dimension that will be moved.
1755
     * @param targetCollectionType The target collection type to move it to. Can be Row, Column or Filter.
1756
     * @param index The index in the collection at which to add.
1757
     * This parameter is optional. If not set it will add it to the end of the collection.
1758
     */
1759
    public moveDimension(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1760
        const prevCollectionType = this.getDimensionType(dimension);
9✔
1761
        if (prevCollectionType === null) return;
9✔
1762
        // remove from old collection
1763
        this._removeDimensionInternal(dimension);
8✔
1764
        // add to target
1765
        this.insertDimensionAt(dimension, targetCollectionType, index);
8✔
1766

1767
        if (prevCollectionType === PivotDimensionType.Column) {
8✔
1768
            this.setupColumns();
3✔
1769
        }
1770
    }
1771

1772
    /**
1773
     * Removes dimension from its currently collection.
1774
     * @remarks
1775
     * This is different than toggleDimension that enabled/disables the dimension.
1776
     * This completely removes the specified dimension from the collection.
1777
     * @example
1778
     * ```typescript
1779
     * this.grid.removeDimension(dimension);
1780
     * ```
1781
     * @param dimension The dimension to be removed.
1782
     */
1783
    public removeDimension(dimension: IPivotDimension) {
1784
        const prevCollectionType = this.getDimensionType(dimension);
4✔
1785
        this._removeDimensionInternal(dimension);
4✔
1786
        if (prevCollectionType === PivotDimensionType.Column) {
4✔
1787
            this.setupColumns();
1✔
1788
        }
1789
        if (prevCollectionType === PivotDimensionType.Filter) {
4✔
1790
            this.reflow();
1✔
1791
        }
1792
        this.pipeTrigger++;
4✔
1793
        this.cdr.detectChanges();
4✔
1794
    }
1795

1796
    /**
1797
     * Toggles the dimension's enabled state on or off.
1798
     * @remarks
1799
     * The dimension remains in its current collection. This just changes its enabled state.
1800
     * @example
1801
     * ```typescript
1802
     * this.grid.toggleDimension(dimension);
1803
     * ```
1804
     * @param dimension The dimension to be toggled.
1805
     */
1806
    public toggleDimension(dimension: IPivotDimension) {
1807
        const dimType = this.getDimensionType(dimension);
12✔
1808
        if (dimType === null) return;
12✔
1809
        const collection = this.getDimensionsByType(dimType);
11✔
1810
        dimension.enabled = !dimension.enabled;
11✔
1811
        if (dimType === PivotDimensionType.Column) {
11✔
1812
            this.setupColumns();
5✔
1813
        }
1814
        if (!dimension.enabled && dimension.filter) {
11✔
1815
            this.filteringService.clearFilter(dimension.memberName);
1✔
1816
        }
1817
        this.pipeTrigger++;
11✔
1818
        this.dimensionsChange.emit({ dimensions: collection, dimensionCollectionType: dimType });
11✔
1819
        this.cdr.detectChanges();
11✔
1820
        if (dimType === PivotDimensionType.Filter) {
11✔
1821
            this.reflow();
3✔
1822
        }
1823
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
11✔
1824
    }
1825

1826
    /**
1827
     * Inserts value at specified index or at the end.
1828
     *
1829
     * @example
1830
     * ```typescript
1831
     * this.grid.insertValueAt(value, 1);
1832
     * ```
1833
     * @param value The value definition that will be added.
1834
     * @param index The index in the collection at which to add.
1835
     * This parameter is optional. If not set it will add it to the end of the collection.
1836
     */
1837
    public insertValueAt(value: IPivotValue, index?: number) {
1838
        if (!this.pivotConfiguration.values) {
7✔
1839
            this.pivotConfiguration.values = [];
1✔
1840
        }
1841
        const values = this.pivotConfiguration.values;
7✔
1842
        if (index !== undefined) {
7✔
1843
            values.splice(index, 0, value);
6✔
1844
        } else {
1845
            values.push(value);
1✔
1846
        }
1847
        this.setupColumns();
7✔
1848
        this.pipeTrigger++;
7✔
1849
        this.cdr.detectChanges();
7✔
1850
        this.valuesChange.emit({ values });
7✔
1851
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
7✔
1852
    }
1853

1854
    /**
1855
     * Move value from its currently at specified index or at the end.
1856
     *
1857
     * @example
1858
     * ```typescript
1859
     * this.grid.moveValue(value, 1);
1860
     * ```
1861
     * @param value The value that will be moved.
1862
     * @param index The index in the collection at which to add.
1863
     * This parameter is optional. If not set it will add it to the end of the collection.
1864
     */
1865
    public moveValue(value: IPivotValue, index?: number) {
1866
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
6✔
1867
        // remove from old index
1868
        this.removeValue(value);
5✔
1869
        // add to new
1870
        this.insertValueAt(value, index);
5✔
1871
    }
1872

1873
    /**
1874
     * Removes value from collection.
1875
     * @remarks
1876
     * This is different than toggleValue that enabled/disables the value.
1877
     * This completely removes the specified value from the collection.
1878
     * @example
1879
     * ```typescript
1880
     * this.grid.removeValue(dimension);
1881
     * ```
1882
     * @param value The value to be removed.
1883
     */
1884
    public removeValue(value: IPivotValue,) {
1885
        const values = this.pivotConfiguration.values;
6✔
1886
        const currentIndex = values.indexOf(value);
6✔
1887
        if (currentIndex !== -1) {
6✔
1888
            values.splice(currentIndex, 1);
6✔
1889
            this.setupColumns();
6✔
1890
            this.pipeTrigger++;
6✔
1891
            this.valuesChange.emit({ values });
6✔
1892
            this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
6✔
1893
        }
1894
    }
1895

1896
    /**
1897
     * Toggles the value's enabled state on or off.
1898
     * @remarks
1899
     * The value remains in its current collection. This just changes its enabled state.
1900
     * @example
1901
     * ```typescript
1902
     * this.grid.toggleValue(value);
1903
     * ```
1904
     * @param value The value to be toggled.
1905
     */
1906
    public toggleValue(value: IPivotValue) {
1907
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
7✔
1908
        value.enabled = !value.enabled;
6✔
1909
        this.setupColumns();
6✔
1910
        this.pipeTrigger++;
6✔
1911
        this.valuesChange.emit({ values: this.pivotConfiguration.values });
6✔
1912
        this.reflow();
6✔
1913
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
6✔
1914
    }
1915

1916
    /**
1917
     * Sort the dimension and its children in the provided direction.
1918
     * @example
1919
     * ```typescript
1920
     * this.grid.sortDimension(dimension, SortingDirection.Asc);
1921
     * ```
1922
     * @param value The value to be toggled.
1923
     */
1924
    public sortDimension(dimension: IPivotDimension, sortDirection: SortingDirection) {
1925
        const dimensionType = this.getDimensionType(dimension);
22✔
1926
        dimension.sortDirection = sortDirection;
22✔
1927
        // apply same sort direction to children.
1928
        let dim = dimension;
22✔
1929
        if (this.pivotUI.rowLayout === PivotRowLayoutType.Vertical) {
22✔
1930
            while (dim.childLevel) {
20✔
1931
                dim.childLevel.sortDirection = dimension.sortDirection;
6✔
1932
                dim = dim.childLevel;
6✔
1933
            }
1934
        }
1935

1936
        this.pipeTrigger++;
22✔
1937
        this.dimensionsSortingExpressionsChange.emit(this.dimensionsSortingExpressions);
22✔
1938
        if (dimensionType === PivotDimensionType.Column) {
22✔
1939
            this.setupColumns();
13✔
1940
        }
1941
        this.cdr.detectChanges();
22✔
1942
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
22✔
1943
    }
1944

1945
    /**
1946
     * Filters a single `IPivotDimension`.
1947
     *
1948
     * @example
1949
     * ```typescript
1950
     * public filter() {
1951
     *      const set = new Set();
1952
     *      set.add('Value 1');
1953
     *      set.add('Value 2');
1954
     *      this.grid1.filterDimension(this.pivotConfigHierarchy.rows[0], set, IgxStringFilteringOperand.instance().condition('in'));
1955
     * }
1956
     * ```
1957
     */
1958
    public filterDimension(dimension: IPivotDimension, value: any, conditionOrExpressionTree?: IFilteringOperation | IFilteringExpressionsTree) {
1959
        this.filteringService.filter(dimension.memberName, value, conditionOrExpressionTree);
2✔
1960
        const dimensionType = this.getDimensionType(dimension);
2✔
1961
        if (dimensionType === PivotDimensionType.Column) {
2✔
1962
            this.setupColumns();
1✔
1963
        }
1964
        this.cdr.detectChanges();
2✔
1965
    }
1966

1967
    /**
1968
     * @hidden @internal
1969
     */
1970
    public getRowDimensionByName(memberName: string) {
1971
        const visibleRows = this.pivotUI.rowLayout === PivotRowLayoutType.Vertical ?
23,738✔
1972
            this.pivotConfiguration.rows :
1973
            PivotUtil.flatten(this.pivotConfiguration.rows);
1974
        const dimIndex = visibleRows.findIndex((target) => target.memberName === memberName);
43,281✔
1975
        const dim = visibleRows[dimIndex];
23,738✔
1976
        return dim;
23,738✔
1977
    }
1978

1979
    /**
1980
     * @hidden @internal
1981
     */
1982
    public getDimensionsByType(dimension: PivotDimensionType) {
1983
        switch (dimension) {
43✔
1984
            case PivotDimensionType.Row:
1985
                if (!this.pivotConfiguration.rows) {
15!
1986
                    this.pivotConfiguration.rows = [];
×
1987
                }
1988
                return this.pivotConfiguration.rows;
15✔
1989
            case PivotDimensionType.Column:
1990
                if (!this.pivotConfiguration.columns) {
16!
1991
                    this.pivotConfiguration.columns = [];
×
1992
                }
1993
                return this.pivotConfiguration.columns;
16✔
1994
            case PivotDimensionType.Filter:
1995
                if (!this.pivotConfiguration.filters) {
11✔
1996
                    this.pivotConfiguration.filters = [];
2✔
1997
                }
1998
                return this.pivotConfiguration.filters;
11✔
1999
            default:
2000
                return null;
1✔
2001
        }
2002
    }
2003

2004
    /**
2005
     * @hidden @internal
2006
     */
2007
    public resizeRowDimensionPixels(dimension: IPivotDimension, newWidth: number) {
2008
        const isPercentageWidth = dimension.width && typeof dimension.width === 'string' && dimension.width.indexOf('%') !== -1;
5✔
2009
        if (isPercentageWidth) {
5✔
2010
            dimension.width = this.reverseDimensionWidthToPercent(newWidth).toFixed(2) + '%';
1✔
2011
        } else {
2012
            dimension.width = newWidth + 'px';
4✔
2013
        }
2014

2015
        // Notify the grid to reflow, to update if horizontal scrollbar needs to be rendered/removed.
2016
        this.pipeTrigger++;
5✔
2017
        this.cdr.detectChanges();
5✔
2018
    }
2019

2020
    /*
2021
    * @hidden
2022
    * @internal
2023
    */
2024
    protected _removeDimensionInternal(dimension) {
2025
        const prevCollectionType = this.getDimensionType(dimension);
12✔
2026
        if (prevCollectionType === null) return;
12✔
2027
        const prevCollection = this.getDimensionsByType(prevCollectionType);
11✔
2028
        const currentIndex = prevCollection.indexOf(dimension);
11✔
2029
        prevCollection.splice(currentIndex, 1);
11✔
2030
        this.pipeTrigger++;
11✔
2031
        this.cdr.detectChanges();
11✔
2032
    }
2033

2034
    protected getDimensionType(dimension: IPivotDimension): PivotDimensionType {
2035
        return PivotUtil.flatten(this.pivotConfiguration.rows).indexOf(dimension) !== -1 ? PivotDimensionType.Row :
63✔
2036
            PivotUtil.flatten(this.pivotConfiguration.columns).indexOf(dimension) !== -1 ? PivotDimensionType.Column :
40✔
2037
                (!!this.pivotConfiguration.filters && PivotUtil.flatten(this.pivotConfiguration.filters).indexOf(dimension) !== -1) ?
39✔
2038
                    PivotDimensionType.Filter : null;
2039
    }
2040

2041
    protected getPivotRowHeaderContentWidth(headerGroup: IgxPivotRowHeaderGroupComponent) {
2042
        const headerSizes = this.getHeaderCellWidth(headerGroup.nativeElement);
×
2043
        return headerSizes.width + headerSizes.padding;
×
2044
    }
2045

2046
    protected getLargesContentWidth(contents: ElementRef[]): string {
2047
        const largest = new Map<number, number>();
2✔
2048
        if (contents.length > 0) {
2✔
2049
            const cellsContentWidths = [];
2✔
2050
            contents.forEach((elem) => {
2✔
2051
                elem instanceof IgxPivotRowHeaderGroupComponent ?
10!
2052
                    cellsContentWidths.push(this.getPivotRowHeaderContentWidth(elem)) :
2053
                    cellsContentWidths.push(this.getHeaderCellWidth(elem.nativeElement).width);
2054
            });
2055
            const index = cellsContentWidths.indexOf(Math.max(...cellsContentWidths));
2✔
2056
            const cellStyle = this.document.defaultView.getComputedStyle(contents[index].nativeElement);
2✔
2057
            const cellPadding = parseFloat(cellStyle.paddingLeft) + parseFloat(cellStyle.paddingRight) +
2✔
2058
                parseFloat(cellStyle.borderLeftWidth) + parseFloat(cellStyle.borderRightWidth);
2059
            largest.set(Math.max(...cellsContentWidths), cellPadding);
2✔
2060
        }
2061
        const largestCell = Math.max(...Array.from(largest.keys()));
2✔
2062
        const width = Math.ceil(largestCell + largest.get(largestCell));
2✔
2063

2064
        if (Number.isNaN(width)) {
2!
2065
            return null;
×
2066
        } else {
2067
            return width + 'px';
2✔
2068
        }
2069
    }
2070

2071
    /** @hidden @internal */
2072
    public get hasHorizontalLayout() {
2073
        return this.pivotUI.rowLayout === PivotRowLayoutType.Horizontal;
116,108✔
2074
    }
2075

2076
    /**
2077
    * @hidden
2078
    */
2079
    public get hasMultipleValues() {
2080
        return this.values.length > 1;
226,138✔
2081
    }
2082

2083
    /**
2084
    * @hidden
2085
    */
2086
    public get excelStyleFilterMaxHeight() {
2087
        // max 10 rows, row size depends on grid size
2088
        const maxHeight = this.renderedRowHeight * 10;
5,597✔
2089
        return `${maxHeight}px`;
5,597✔
2090
    }
2091

2092
    /**
2093
    * @hidden
2094
    */
2095
    public get excelStyleFilterMinHeight(): string {
2096
        // min 5 rows, row size depends on grid size
2097
        const minHeight = this.renderedRowHeight * 5;
5,597✔
2098
        return `${minHeight}px`;
5,597✔
2099
    }
2100

2101
    /** @hidden @internal */
2102
    public override get activeDescendant(): string | undefined {
2103
        if (this.navigation.isRowHeaderActive || this.navigation.isRowDimensionHeaderActive) {
5,600✔
2104
            return;
376✔
2105
        }
2106
        return super.activeDescendant;
5,224✔
2107
    }
2108

2109
    /** @hidden @internal */
2110
    public get headerRowActiveDescendant() {
2111
        const activeElem = this.navigation.activeNode;
4,191✔
2112
        if (!activeElem || !Object.keys(activeElem).length || !this.navigation.isRowHeaderActive) {
4,191✔
2113
            return null;
3,940✔
2114
        }
2115

2116
        const rowDimensions = this.rowDimensionContentCollection.length > 0 ?
251✔
2117
            this.rowDimensionContentCollection.toArray() :
2118
            this.rowDimensionMrlComponent.rowDimensionContentCollection.toArray();
2119

2120
        const rowDimensionContentActive = rowDimensions.find(rd => rd && rd.headerGroups?.some(hg => hg.active));
854✔
2121
        const activeHeader = rowDimensionContentActive?.headerGroups.toArray().find(hg => hg.active);
251✔
2122

2123
        return activeHeader ? `${this.id}_${activeHeader.title}` : null;
251✔
2124
    }
2125

2126
    protected resolveToggle(groupColumn: ColumnType, state: boolean) {
2127
        if (!groupColumn) return;
8!
2128
        groupColumn.hidden = state;
8✔
2129
        this.columnGroupStates.set(groupColumn.field, state);
8✔
2130
        const childrenTotal = this.hasMultipleValues ?
8✔
2131
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === this.values.length) :
44✔
2132
            groupColumn.children.filter(x => !x.columnGroup);
3✔
2133
        const childrenSubgroups = this.hasMultipleValues ?
8✔
2134
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === 0) :
44✔
2135
            groupColumn.children.filter(x => x.columnGroup);
3✔
2136
        childrenTotal.forEach(group => {
8✔
2137
            const newState = this.columnGroupStates.get(group.field) || state;
18✔
2138
            if (newState) {
18✔
2139
                group.headerTemplate = this.headerTemplate;
11✔
2140
            } else {
2141
                group.headerTemplate = undefined;
7✔
2142
            }
2143
        });
2144
        if (!groupColumn.hidden && childrenSubgroups.length > 0) {
8✔
2145
            childrenSubgroups.forEach(group => {
1✔
2146
                const newState = this.columnGroupStates.get(group.field) || state;
3✔
2147
                this.resolveToggle(group, newState);
3✔
2148
            });
2149
        }
2150
    }
2151

2152
    protected override buildDataView(data: any[]) {
2153
        this._dataView = data;
900✔
2154
    }
2155

2156
    protected override onContentSizeChange() {
2157
        super.onContentSizeChange();
18✔
2158
        this.updateDefaultRowHeight();
18✔
2159
    }
2160

2161
    /**
2162
     * @hidden @internal
2163
     */
2164
    protected override getDataBasedBodyHeight(): number {
2165
        const dvl = this.dataView?.length || 0;
96!
2166
        return dvl < this._defaultTargetRecordNumber ? 0 : this.defaultTargetBodyHeight;
96✔
2167
    }
2168

2169
    protected override horizontalScrollHandler(event) {
2170
        const scrollLeft = event.target.scrollLeft;
2✔
2171
        this.theadRow.headerContainers.forEach(headerForOf => {
2✔
2172
            headerForOf.onHScroll(scrollLeft);
4✔
2173
        });
2174
        super.horizontalScrollHandler(event);
2✔
2175
    }
2176

2177
    protected override verticalScrollHandler(event) {
2178
        this.verticalRowDimScrollContainers.forEach(x => {
×
2179
            x.onScroll(event);
×
2180
        });
2181
        super.verticalScrollHandler(event);
×
2182
    }
2183

2184
    /**
2185
     * @hidden
2186
     */
2187
    protected override autogenerateColumns() {
2188
        let columns = [];
276✔
2189
        const data = this.gridAPI.filterDataByExpressions(this.filteringExpressionsTree);
276✔
2190
        this.dimensionDataColumns = this.generateDimensionColumns();
276✔
2191
        const flattenedColumnsWithSorting = PivotUtil.flatten(this.columnDimensions).filter(dim => dim.sortDirection);
277✔
2192
        const expressions = flattenedColumnsWithSorting.length > 0 ? PivotSortUtil.generateDimensionSortingExpressions(flattenedColumnsWithSorting) : [];
276✔
2193
        let sortedData = data;
276✔
2194
        if (expressions.length > 0) {
276✔
2195
            sortedData = DataUtil.sort(cloneArray(data), expressions, this.sortStrategy, this);
12✔
2196
        }
2197
        let fieldsMap;
2198
        if (this.pivotConfiguration.columnStrategy && this.pivotConfiguration.columnStrategy instanceof NoopPivotDimensionsStrategy) {
276✔
2199
            const fields = this.generateDataFields(sortedData);
5✔
2200
            if (fields.length === 0) return;
5✔
2201
            const rowFields = PivotUtil.flatten(this.pivotConfiguration.rows).map(x => x.memberName);
6✔
2202
            const keyFields = Object.values(this.pivotKeys);
3✔
2203
            const filteredFields = fields.filter(x => rowFields.indexOf(x) === -1 && keyFields.indexOf(x) === -1 &&
18✔
2204
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.level) === -1 &&
2205
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.records) === -1);
2206
            fieldsMap = this.generateFromData(filteredFields);
3✔
2207
        } else {
2208
            fieldsMap = PivotUtil.getFieldsHierarchy(
271✔
2209
                sortedData,
2210
                this.columnDimensions,
2211
                PivotDimensionType.Column,
2212
                this.pivotKeys,
2213
                this.pivotValueCloneStrategy
2214
            );
2215
        }
2216
        columns = this.generateColumnHierarchy(fieldsMap, sortedData);
274✔
2217
        this._autoGeneratedCols = columns;
274✔
2218
        // reset expansion states if any are stored.
2219
        this.columnGroupStates.forEach((value, key) => {
274✔
2220
            if (value) {
1✔
2221
                const primaryColumn = columns.find(x => x.field === key && x.headerTemplate === this.headerTemplate);
1✔
2222
                const groupSummaryColumn = columns.find(x => x.field === key && x.headerTemplate !== this.headerTemplate);
14✔
2223
                this.toggleRowGroup(primaryColumn, value);
1✔
2224
                if (groupSummaryColumn) {
1✔
2225
                    groupSummaryColumn.headerTemplate = this.headerTemplate;
1✔
2226
                }
2227
            }
2228
        });
2229

2230
        this.updateColumns(columns);
274✔
2231
        this.pipeTrigger++;
274✔
2232
        this.reflow();
274✔
2233
    }
2234

2235
    protected generateDimensionColumns(): IgxColumnComponent[] {
2236
        const columns = [];
310✔
2237
        this.allVisibleDimensions.forEach((dim) => {
310✔
2238
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
890✔
2239
            ref.instance.field = dim.memberName;
890✔
2240
            ref.instance.header = dim.displayName || dim.memberName;
890✔
2241
            ref.instance.headerTemplate = this.rowDimensionHeaderTemplate;
890✔
2242
            ref.instance.resizable = this.rowDimensionResizing;
890✔
2243
            ref.instance.sortable = dim.sortable === undefined ? true : dim.sortable;
890!
2244
            ref.instance.width = this.rowDimensionWidth(dim);
890✔
2245
            ref.instance.filteringIgnoreCase = false;
890✔
2246
            ref.changeDetectorRef.detectChanges();
890✔
2247
            columns.push(ref.instance);
890✔
2248
        });
2249
        return columns;
310✔
2250
    }
2251

2252
    protected override calculateGridSizes(recalcFeatureWidth = true) {
578✔
2253
        super.calculateGridSizes(recalcFeatureWidth);
578✔
2254
        if (this.hasDimensionsToAutosize) {
578✔
2255
            this.cdr.detectChanges();
2✔
2256
            runAfterRenderOnce(this.injector, () => {
2✔
2257
                requestAnimationFrame(() => {
2✔
2258
                    this.autoSizeDimensionsInView();
2✔
2259
                });
2260
            });
2261
        }
2262
    }
2263

2264
    protected getContentCollection(dimenstion: IPivotDimension) {
2265
        let contentCollection;
2266
        if (this.hasHorizontalLayout) {
3!
2267
            const allMrlContents = this.rowDimensionMrlRowsCollection.map(mrlRow => mrlRow.contentCells.toArray()).flat();
×
2268
            contentCollection = allMrlContents.filter(cell => cell.rootDimension === dimenstion);
×
2269
        } else {
2270
            contentCollection = this.rowDimensionContentCollection.toArray();
3✔
2271
        }
2272
        return contentCollection;
3✔
2273
    }
2274

2275
    protected autoSizeDimensionsInView() {
2276
        if (!this.hasDimensionsToAutosize) return;
2✔
2277
        for (const dim of this.visibleRowDimensions) {
1✔
2278
            if (dim.width === 'auto') {
1✔
2279
                const contentWidths = [];
1✔
2280
                const relatedDims = PivotUtil.flatten([dim]).map(x => x.memberName);
2✔
2281
                const contentCollection = this.getContentCollection(dim);
1✔
2282
                const content = contentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
5✔
2283
                const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
5✔
2284
                headers.forEach((header) => contentWidths.push(header?.nativeElement?.offsetWidth || 0));
5!
2285
                if (this.pivotUI.showRowHeaders) {
1!
2286
                    const dimensionHeader = this.theadRow.rowDimensionHeaders.find(x => x.column.field === dim.memberName);
×
2287
                    contentWidths.push(parseFloat(this.getLargesContentWidth([dimensionHeader])));
×
2288
                }
2289
                const max = Math.max(...contentWidths);
1✔
2290
                if (max === 0) {
1!
2291
                    // cells not in DOM yet...
2292
                    continue;
×
2293
                }
2294
                const maxSize = Math.ceil(Math.max(...contentWidths));
1✔
2295
                dim.autoWidth = maxSize;
1✔
2296
            }
2297
        }
2298

2299
        if (this.isColumnWidthSum) {
1!
2300
            this.calcWidth = this.getColumnWidthSum();
×
2301
        }
2302
    }
2303

2304
    /** @hidden @internal */
2305
    public get hasDimensionsToAutosize() {
2306
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
916✔
2307
    }
2308

2309
    protected generateFromData(fields: string[]) {
2310
        const separator = this.pivotKeys.columnDimensionSeparator;
3✔
2311
        const dataArr = fields.map(x => x.split(separator)).sort(x => x.length);
12✔
2312
        const hierarchy = new Map<string, any>();
3✔
2313
        const columnDimensions = PivotUtil.flatten(this.columnDimensions);
3✔
2314
        dataArr.forEach(arr => {
3✔
2315
            let currentHierarchy = hierarchy;
12✔
2316
            const path = [];
12✔
2317
            let index = 0;
12✔
2318
            for (const val of arr) {
12✔
2319
                path.push(val);
12✔
2320
                const newPath = path.join(separator);
12✔
2321
                let targetHierarchy = currentHierarchy.get(newPath);
12✔
2322
                if (!targetHierarchy) {
12✔
2323
                    const currentColumnDimension = columnDimensions[index];
12✔
2324
                    currentHierarchy.set(newPath, { value: newPath, expandable: !!currentColumnDimension.childLevel, children: new Map<string, any>(), dimension: currentColumnDimension });
12✔
2325
                    targetHierarchy = currentHierarchy.get(newPath);
12✔
2326
                }
2327
                currentHierarchy = targetHierarchy.children;
12✔
2328
                index++;
12✔
2329
            }
2330
        });
2331
        return hierarchy;
3✔
2332
    }
2333
    protected generateColumnHierarchy(fields: Map<string, any>, data, parent = null): IgxColumnComponent[] {
274✔
2334
        let columns = [];
338✔
2335
        if (fields.size === 0) {
338✔
2336
            this.values.forEach((value) => {
20✔
2337
                const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
21✔
2338
                let columnDataType = value.dataType || this.resolveDataTypes(data.length ? data[0][value.member] : null);
21!
2339

2340
                if (value.aggregate?.key?.toLowerCase() === 'count' && (columnDataType === GridColumnDataType.Currency || columnDataType == GridColumnDataType.Percent)) {
21!
2341
                    columnDataType = GridColumnDataType.Number;
×
2342
                }
2343

2344
                ref.instance.header = value.displayName;
21✔
2345
                ref.instance.field = value.member;
21✔
2346
                ref.instance.parent = parent;
21✔
2347
                ref.instance.sortable = true;
21✔
2348
                ref.instance.dataType = columnDataType;
21✔
2349
                ref.instance.formatter = value.formatter;
21✔
2350
                columns.push(ref.instance);
21✔
2351
            });
2352
            return columns;
20✔
2353
        }
2354
        const currentFields = fields;
318✔
2355
        currentFields.forEach((value) => {
318✔
2356
            let shouldGenerate = true;
1,170✔
2357
            if (data.length === 0) {
1,170!
2358
                shouldGenerate = false;
×
2359
            }
2360
            if (shouldGenerate && (value.children == null || value.children.length === 0 || value.children.size === 0)) {
1,170✔
2361
                const col = this.createColumnForDimension(value, data, parent, this.hasMultipleValues);
1,106✔
2362

2363
                if (!this.hasMultipleValues && this.values.length > 0) {
1,106✔
2364
                    PivotUtil.updateColumnTypeByAggregator([col], this.values[0], true);
160✔
2365
                }
2366

2367
                columns.push(col);
1,106✔
2368
                if (this.hasMultipleValues) {
1,106✔
2369
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
935✔
2370

2371
                    measureChildren.forEach((child, index) => {
935✔
2372
                        const pivotValue = this.values[index];
1,875✔
2373
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
1,875✔
2374
                    });
2375

2376
                    col.children.reset(measureChildren);
935✔
2377
                    columns = columns.concat(measureChildren);
935✔
2378
                }
2379

2380
            } else if (shouldGenerate) {
64✔
2381
                const col = this.createColumnForDimension(value, data, parent, true);
64✔
2382
                if (value.expandable) {
64✔
2383
                    col.headerTemplate = this.headerTemplate;
21✔
2384
                }
2385
                const children = this.generateColumnHierarchy(value.children, data, col);
64✔
2386
                const filteredChildren = children.filter(x => x.level === col.level + 1);
456✔
2387
                columns.push(col);
64✔
2388
                if (this.hasMultipleValues) {
64✔
2389
                    let measureChildren = this.getMeasureChildren(data, col, true, value.dimension.width);
63✔
2390
                    const nestedChildren = filteredChildren;
63✔
2391
                    //const allChildren = children.concat(measureChildren);
2392
                    col.children.reset(nestedChildren);
63✔
2393
                    columns = columns.concat(children);
63✔
2394
                    if (value.dimension.childLevel) {
63✔
2395
                        const sibling = this.createColumnForDimension(value, data, parent, true);
20✔
2396
                        columns.push(sibling);
20✔
2397

2398
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2399
                        sibling.children.reset(measureChildren);
20✔
2400
                        columns = columns.concat(measureChildren);
20✔
2401
                    }
2402

2403
                } else {
2404
                    col.children.reset(filteredChildren);
1✔
2405
                    columns = columns.concat(children);
1✔
2406
                    if (value.dimension.childLevel) {
1✔
2407
                        const sibling = this.createColumnForDimension(value, data, parent, false);
1✔
2408
                        columns.push(sibling);
1✔
2409
                    }
2410
                }
2411
            }
2412
        });
2413

2414
        return columns;
318✔
2415
    }
2416

2417

2418
    protected generateConfig() {
2419
        if (!this.data) return;
1!
2420

2421
        const data = this.data;
1✔
2422
        const fields = this.generateDataFields(data);
1✔
2423
        const columnDimensions: IPivotDimension[] = [];
1✔
2424
        const rowDimensions: IPivotDimension[] = [];
1✔
2425
        const values: IPivotValue[] = [];
1✔
2426
        let isFirstDate = true;
1✔
2427
        fields.forEach((field) => {
1✔
2428
            const dataType = this.resolveDataTypes(data[0][field]);
6✔
2429
            switch (dataType) {
6✔
2430
                case "number":
2431
                    {
2432
                        const value: IPivotValue = {
2✔
2433
                            member: field,
2434
                            displayName: field,
2435
                            dataType: dataType,
2436
                            aggregate: {
2437
                                key: 'sum',
2438
                                label: 'Sum',
2439
                                aggregatorName: "SUM"
2440
                            },
2441
                            enabled: true
2442
                        };
2443
                        values.push(value);
2✔
2444
                        break;
2✔
2445
                    }
2446
                case "date":
2447
                    {
2448
                        const dimension: IPivotDimension = new IgxPivotDateDimension(
1✔
2449
                            {
2450
                                memberName: field,
2451
                                enabled: isFirstDate,
2452
                                dataType: dataType
2453
                            }
2454
                        )
2455
                        rowDimensions.push(dimension);
1✔
2456
                        isFirstDate = false;
1✔
2457
                        break;
1✔
2458
                    }
2459
                default: {
2460
                    const dimension: IPivotDimension = {
3✔
2461
                        memberName: field,
2462
                        enabled: false,
2463
                        dataType: dataType
2464
                    };
2465
                    columnDimensions.push(dimension);
3✔
2466
                    break;
3✔
2467
                }
2468
            }
2469
        });
2470
        const config: IPivotConfiguration = {
1✔
2471
            columns: columnDimensions,
2472
            rows: rowDimensions,
2473
            values: values
2474
        };
2475
        this.pivotConfiguration = config;
1✔
2476
    }
2477

2478
    protected createColumnForDimension(value: any, data: any, parent: ColumnType, isGroup: boolean) {
2479
        const key = value.value;
1,191✔
2480
        const ref = isGroup ?
1,191✔
2481
            createComponent(IgxColumnGroupComponent, { environmentInjector: this.envInjector, elementInjector: this.injector }) :
2482
            createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2483
        ref.instance.header = parent != null ? key.split(parent.header + this.pivotKeys.columnDimensionSeparator)[1] : key;
1,191✔
2484
        ref.instance.field = key;
1,191✔
2485
        ref.instance.parent = parent;
1,191✔
2486
        if (value.dimension.width) {
1,191!
2487
            ref.instance.width = value.dimension.width;
×
2488
        }
2489
        const valueDefinition = this.values[0];
1,191✔
2490
        ref.instance.dataType = valueDefinition?.dataType || this.resolveDataTypes(data[0][valueDefinition?.member]);
1,191✔
2491
        ref.instance.formatter = valueDefinition?.formatter;
1,191✔
2492
        ref.instance.sortable = true;
1,191✔
2493
        ref.changeDetectorRef.detectChanges();
1,191✔
2494
        return ref.instance;
1,191✔
2495
    }
2496

2497
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2498
        if (dim.width) {
×
2499
            return dim.width;
×
2500
        }
2501
        return this.minColumnWidth + 'px';
×
2502
    }
2503

2504
    protected getMeasureChildren(data, parent, hidden, parentWidth) {
2505
        const cols = [];
1,018✔
2506
        const count = this.values.length;
1,018✔
2507
        const childWidth = parseInt(parentWidth, 10) / count;
1,018✔
2508
        const isPercent = parentWidth && parentWidth.indexOf('%') !== -1;
1,018!
2509
        const isAuto = parentWidth && parentWidth.indexOf('auto') !== -1;
1,018!
2510
        this.values.forEach(val => {
1,018✔
2511
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2,041✔
2512
            ref.instance.header = val.displayName || val.member;
2,041✔
2513
            ref.instance.field = parent.field + this.pivotKeys.columnDimensionSeparator + val.member;
2,041✔
2514
            ref.instance.parent = parent;
2,041✔
2515
            if (parentWidth) {
2,041!
2516
                ref.instance.width = isAuto ? 'auto' : isPercent ? childWidth + '%' : childWidth + 'px';
×
2517
            }
2518
            ref.instance.hidden = hidden;
2,041✔
2519
            ref.instance.sortable = this._sortableColumns;
2,041✔
2520
            ref.instance.dataType = val.dataType || this.resolveDataTypes(data[0][val.member]);
2,041✔
2521
            ref.instance.formatter = val.formatter;
2,041✔
2522
            ref.changeDetectorRef.detectChanges();
2,041✔
2523
            cols.push(ref.instance);
2,041✔
2524
        });
2525
        return cols;
1,018✔
2526
    }
2527

2528
    /**
2529
    * @hidden @internal
2530
    */
2531
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2532
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2533

2534
    /**
2535
     * Gets/Sets a custom template when pivot grid is empty.
2536
     *
2537
     * @example
2538
     * ```html
2539
     * <igx-pivot-grid [emptyPivotGridTemplate]="myTemplate"><igx-pivot-grid>
2540
     * ```
2541
     */
2542
    @Input()
2543
    public emptyPivotGridTemplate: TemplateRef<void>;
2544

2545
    /**
2546
    * @hidden @internal
2547
    */
2548
    public override get template(): TemplateRef<any> {
2549
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
2,800✔
2550
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
2,800✔
2551
            // no enabled values and dimensions
2552
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
71✔
2553
        }
2554
        return super.template;
2,729✔
2555
    }
2556

2557
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2558
        const dimensions = PivotUtil.flatten(this.allDimensions);
183✔
2559
        dimensions.forEach(dim => {
183✔
2560
            this.dimensionInit.emit(dim);
656✔
2561
        });
2562
        const values = pivotConfig?.values;
183✔
2563
        values?.forEach(val => {
183✔
2564
            this.valueInit.emit(val);
328✔
2565
        });
2566
    }
2567

2568
    protected rowDimensionByName(memberName: string) {
2569
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2570
    }
2571

2572
    protected calculateResizerTop() {
2573
        return this.pivotUI.showRowHeaders ?
33✔
2574
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
14!
2575
            this.theadRow.nativeElement.offsetHeight;
2576
    }
2577

2578
    protected override updateDefaultRowHeight() {
2579
        super.updateDefaultRowHeight();
530✔
2580
        if (this.hasHorizontalLayout) {
530✔
2581
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2582
            this.regroupTrigger++;
14✔
2583
        } else {
2584
            this.pipeTrigger++;
516✔
2585
        }
2586
    }
2587

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

2590
    /**
2591
     * Sets the locale and resourceStrings data based on the grid's properties for all IgxPivotDateDimensions in the config.
2592
     * By default search all dimensions (even not enabled).
2593
     * @param entryDimensions Entry dimension on which to check for IgxPivotDateDimension instead of the default.
2594
     */
2595
    protected setDateDimensionsLocaleData(entryDimensions?: IPivotDimension[]) {
2596
        const topDimensions = entryDimensions ?? [...this.allDimensions];
196✔
2597
        for (const dim of topDimensions) {
196✔
2598
            let foundDateDim: IgxPivotDateDimension | undefined;
2599
            if (dim instanceof IgxPivotDateDimension) {
503✔
2600
                foundDateDim = dim;
1✔
2601
            } else if (dim.childLevel) {
502✔
2602
                var curChild: IPivotDimension | undefined = dim.childLevel;
166✔
2603
                while(curChild) {
166✔
2604
                    if (curChild instanceof IgxPivotDateDimension) {
168!
2605
                        foundDateDim = curChild;
×
2606
                        break;
×
2607
                    }
2608
                    curChild = curChild.childLevel;
168✔
2609
                }
2610
            }
2611

2612
            if (foundDateDim) {
503✔
2613
                foundDateDim.resourceStrings = this.resourceStrings;
1✔
2614
                if (this.locale) {
1✔
2615
                    foundDateDim.locale = this.locale;
1✔
2616
                }
2617
            }
2618
        }
2619
    }
2620

2621
    /**
2622
     * @hidden @internal
2623
     */
2624
    public createRow(index: number, data?: any): RowType {
2625
        let row: RowType;
2626

2627
        const dataIndex = this._getDataViewIndex(index);
×
2628
        const rec = data ?? this.dataView[dataIndex];
×
2629

2630

2631
        if (!row && rec) {
×
2632
            row = new IgxPivotGridRow(this, index, rec);
×
2633
        }
2634
        return row;
×
2635
    }
2636
}
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