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

IgniteUI / igniteui-angular / 30820539303

03 Aug 2026 01:59PM UTC coverage: 90.157% (-0.03%) from 90.19%
30820539303

Pull #15125

github

web-flow
Merge cf62d17ef into 75c7853d3
Pull Request #15125: refactor(*): bundle styles with components

14962 of 17433 branches covered (85.83%)

Branch coverage included in aggregate %.

30113 of 32563 relevant lines covered (92.48%)

37531.2 hits per line

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

86.76
/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,197,216✔
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,084✔
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,767✔
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) {
709✔
470
            return ɵSize.Small;
4✔
471
        }
472
        return super.gridSize;
705✔
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,878✔
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,030✔
543
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
31✔
544
        } else {
545
            return MINIMUM_COLUMN_WIDTH;
52,999✔
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;
215,939✔
712
    }
713
    /** @hidden @internal */
714
    public override get type(): GridType["type"] {
715
        return 'pivot';
6,736✔
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,368✔
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,799✔
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,735✔
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,580✔
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,020✔
922
    }
923

924
    /**
925
     * @hidden @internal
926
     */
927
    public override get pinnedStartWidth() {
928
        return super.pinnedStartWidth;
3,378✔
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,639✔
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,649✔
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,418✔
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();
×
1095
                // Since the columns are kinda static, due to assigning DisplayName on init, they need to be regenerated.
1096
                this.setupColumns();
×
1097
            }, this);
1098
        });
1099
        if (this.valueChipTemplateDirective) {
158!
1100
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
×
1101
        }
1102
        if (this.rowDimensionHeaderDirective) {
158!
1103
            this.rowDimensionHeaderTemplate = this.rowDimensionHeaderDirective.template;
×
1104
        }
1105
    }
1106

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

1115
    }
1116

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

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

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

1152
    protected get allVisibleDimensions() {
1153
        const config = this._pivotConfiguration;
309✔
1154
        if (!config) return [];
309✔
1155
        const uniqueVisibleRowDims = this.visibleRowDimensions.filter(dim => !config.rows.find(configRow => configRow.memberName === dim.memberName));
337✔
1156
        const rows = (config.rows || []).concat(...uniqueVisibleRowDims);
305!
1157
        return rows.concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
888!
1158
    }
1159

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1353
    public get visibleRowDimensions() {
1354
        return this._visibleRowDimensions || this.rowDimensions;
51,747!
1355
    }
1356

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

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

1367
    /** @hidden @internal */
1368
    public get values() {
1369
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
899,931✔
1370
    }
1371

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

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

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

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

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

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

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

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

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

1433
    public override set totalRecords(_total: number) {
1434
    }
1435

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

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

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

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

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

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

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

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

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

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

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

1506
    /**
1507
     * @hidden @internal
1508
     */
1509
    public override get pinnedRowHeight() {
1510
        return;
3,481✔
1511
    }
1512

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

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

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

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

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

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

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

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

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

1572
    /**
1573
     * @hidden @internal
1574
     */
1575
    public override clearSearch() { }
1576

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

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

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

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

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

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

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

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

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

1663
    /**
1664
    * @hidden @internal
1665
    */
1666
    public override setupColumns() {
1667
        super.setupColumns();
275✔
1668
    }
1669

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

1678
        super.dataRebinding(event);
860✔
1679
    }
1680

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2074
    /**
2075
    * @hidden
2076
    */
2077
    public get hasMultipleValues() {
2078
        return this.values.length > 1;
225,967✔
2079
    }
2080

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

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

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

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

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

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

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

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

2150
    protected override buildDataView(data: any[]) {
2151
        this._dataView = data;
899✔
2152
    }
2153

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

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

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

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

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

2228
        this.updateColumns(columns);
273✔
2229
        this.pipeTrigger++;
273✔
2230
        this.reflow();
273✔
2231
    }
2232

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

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

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

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

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

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

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

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

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

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

2365
                columns.push(col);
1,103✔
2366
                if (this.hasMultipleValues) {
1,103✔
2367
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
932✔
2368

2369
                    measureChildren.forEach((child, index) => {
932✔
2370
                        const pivotValue = this.values[index];
1,869✔
2371
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
1,869✔
2372
                    });
2373

2374
                    col.children.reset(measureChildren);
932✔
2375
                    columns = columns.concat(measureChildren);
932✔
2376
                }
2377

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

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

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

2412
        return columns;
317✔
2413
    }
2414

2415

2416
    protected generateConfig() {
2417
        if (!this.data) return;
1!
2418

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

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

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

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

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

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

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

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

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

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

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

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

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

2610
            if (foundDateDim) {
501✔
2611
                foundDateDim.resourceStrings = this.resourceStrings;
1✔
2612
                if (this.locale) {
1✔
2613
                    foundDateDim.locale = this.locale;
1✔
2614
                }
2615
            }
2616
        }
2617
    }
2618

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

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

2628

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