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

IgniteUI / igniteui-angular / 20191011486

13 Dec 2025 10:50AM UTC coverage: 91.504% (+0.003%) from 91.501%
20191011486

push

github

web-flow
refactor(*): New localization implementation. (#16034)

14236 of 16778 branches covered (84.85%)

378 of 419 new or added lines in 61 files covered. (90.21%)

1 existing line in 1 file now uncovered.

28649 of 31309 relevant lines covered (91.5%)

34896.51 hits per line

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

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

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

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

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

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

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

186

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

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

213

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

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

240

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

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

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

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

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

282
    @Input()
283
    public rowDimensionHeaderTemplate: TemplateRef<IgxColumnTemplateContext>;
284

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

306
    /* mustSetInCodePlatforms: WebComponents;Blazor */
307
    public get pivotConfiguration() {
308
        return this._pivotConfiguration || { rows: null, columns: null, values: null, filters: null };
972,917✔
309
    }
310

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

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

340
    public get pivotUI() {
341
        return this._pivotUI;
113,715✔
342
    }
343

344
    /**
345
     * @hidden @internal
346
     */
347
    @HostBinding('attr.role')
348
    public role = 'grid';
148✔
349

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

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

369
    /** @hidden @internal */
370
    public override get gridSize() {
371
        if (this.superCompactMode) {
709✔
372
            return ɵSize.Small;
4✔
373
        }
374
        return super.gridSize;
705✔
375
    }
376

377

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

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

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

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

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

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

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

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

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

440
    /**
441
     * @hidden @internal
442
     */
443
    public override get minColumnWidth() {
444
        if (this.superCompactMode) {
58,441✔
445
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
46✔
446
        } else {
447
            return MINIMUM_COLUMN_WIDTH;
58,395✔
448
        }
449
    }
450

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

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

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

469
    /**
470
     * @hidden @internal
471
     */
472
    @Input()
473
    public override autoGenerateExclude: string[] = [];
148✔
474

475
    /**
476
     * @hidden @internal
477
     */
478
    @Input()
479
    public override snackbarDisplayTime = 6000;
148✔
480

481
    /**
482
     * @hidden @internal
483
     */
484
    @Output()
485
    public override cellEdit = new EventEmitter<IGridEditEventArgs>();
148✔
486

487
    /**
488
     * @hidden @internal
489
     */
490
    @Output()
491
    public override cellEditDone = new EventEmitter<IGridEditDoneEventArgs>();
148✔
492

493
    /**
494
     * @hidden @internal
495
     */
496
    @Output()
497
    public override cellEditEnter = new EventEmitter<IGridEditEventArgs>();
148✔
498

499
    /**
500
     * @hidden @internal
501
     */
502
    @Output()
503
    public override cellEditExit = new EventEmitter<IGridEditDoneEventArgs>();
148✔
504

505
    /**
506
     * @hidden @internal
507
     */
508
    @Output()
509
    public override columnMovingStart = new EventEmitter<IColumnMovingStartEventArgs>();
148✔
510

511
    /**
512
     * @hidden @internal
513
     */
514
    @Output()
515
    public override columnMoving = new EventEmitter<IColumnMovingEventArgs>();
148✔
516

517
    /**
518
     * @hidden @internal
519
     */
520
    @Output()
521
    public override columnMovingEnd = new EventEmitter<IColumnMovingEndEventArgs>();
148✔
522

523
    /**
524
     * @hidden @internal
525
     */
526
    @Output()
527
    public override columnPin = new EventEmitter<IPinColumnCancellableEventArgs>();
148✔
528

529
    /**
530
     * @hidden @internal
531
     */
532
    @Output()
533
    public override columnPinned = new EventEmitter<IPinColumnEventArgs>();
148✔
534

535
    /**
536
     * @hidden @internal
537
     */
538
    @Output()
539
    public override rowAdd = new EventEmitter<IRowDataCancelableEventArgs>();
148✔
540

541
    /**
542
     * @hidden @internal
543
     */
544
    @Output()
545
    public override rowAdded = new EventEmitter<IRowDataEventArgs>();
148✔
546

547
    /**
548
     * @hidden @internal
549
     */
550
    @Output()
551
    public override rowDeleted = new EventEmitter<IRowDataEventArgs>();
148✔
552

553
    /**
554
     * @hidden @internal
555
     */
556
    @Output()
557
    public override rowDelete = new EventEmitter<IRowDataCancelableEventArgs>();
148✔
558

559
    /**
560
     * @hidden @internal
561
     */
562
    @Output()
563
    public override rowDragStart = new EventEmitter<IRowDragStartEventArgs>();
148✔
564

565
    /**
566
     * @hidden @internal
567
     */
568
    @Output()
569
    public override rowDragEnd = new EventEmitter<IRowDragEndEventArgs>();
148✔
570

571
    /**
572
     * @hidden @internal
573
     */
574
    @Output()
575
    public override rowEditEnter = new EventEmitter<IGridEditEventArgs>();
148✔
576

577
    /**
578
     * @hidden @internal
579
     */
580
    @Output()
581
    public override rowEdit = new EventEmitter<IGridEditEventArgs>();
148✔
582

583
    /**
584
     * @hidden @internal
585
     */
586
    @Output()
587
    public override rowEditDone = new EventEmitter<IGridEditDoneEventArgs>();
148✔
588

589
    /**
590
     * @hidden @internal
591
     */
592
    @Output()
593
    public override rowEditExit = new EventEmitter<IGridEditDoneEventArgs>();
148✔
594

595
    /**
596
     * @hidden @internal
597
     */
598
    @Output()
599
    public override rowPinning = new EventEmitter<IPinRowEventArgs>();
148✔
600

601
    /**
602
     * @hidden @internal
603
     */
604
    @Output()
605
    public override rowPinned = new EventEmitter<IPinRowEventArgs>();
148✔
606

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

620
    /**
621
     * @hidden @internal
622
     */
623
    public override dragRowID = null;
148✔
624

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

632
    /**
633
     * @hidden @internal
634
     */
635
    public rowDimensionResizing = true;
148✔
636

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

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

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

671
    public set defaultExpandState(val: boolean) {
672
        this._defaultExpandState = val;
138✔
673
    }
674

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

683
    public override set pagingMode(_val: GridPagingMode) {
684
    }
685

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

695
    public override set hideRowSelectors(_value: boolean) {
696
    }
697

698
    /**
699
     * @hidden @internal
700
     */
701
    public override autoGenerate = true;
148✔
702

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

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

718
    public override set shouldGenerate(value: boolean) {
719
    }
720

721
    /**
722
     * @hidden @internal
723
     */
724
    public override moving = false;
148✔
725

726
    /**
727
     * @hidden @internal
728
     */
729
    public override toolbarExporting = new EventEmitter<IGridToolbarExportEventArgs>();
148✔
730

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

739

740
    public override set rowDraggable(_val: boolean) {
741
    }
742

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

751
    public override set allowAdvancedFiltering(_value) {
752
    }
753

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

762
    public override set filterMode(_value: FilterMode) {
763
    }
764

765
    /**
766
     * @hidden @internal
767
     */
768
    @Input({ transform: booleanAttribute })
769
    public override get allowFiltering() {
770
        return false;
38,169✔
771
    }
772

773
    public override set allowFiltering(_value) {
774
    }
775

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

784
    public override set page(_val: number) {
785
    }
786

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

795
    public override set perPage(_val: number) {
796
    }
797

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

805
    /**
806
    * @hidden @internal
807
    */
808
    public override get unpinnedColumns(): IgxColumnComponent[] {
809
        return super.unpinnedColumns;
29,285✔
810
    }
811

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

819
    /**
820
    * @hidden @internal
821
    */
822
    public override get unpinnedWidth() {
823
        return super.unpinnedWidth;
24,816✔
824
    }
825

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

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

840
    public override get summaryRowHeight(): number {
841
        return 0;
642✔
842
    }
843

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

851

852

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

860
    public override set dragIndicatorIconTemplate(_val: TemplateRef<any>) {
861
    }
862

863
    /**
864
     * @hidden @internal
865
     */
866
    @WatchChanges()
867
    @Input({ transform: booleanAttribute })
868
    public override get rowEditable(): boolean {
869
        return;
241,917✔
870
    }
871

872
    public override set rowEditable(_val: boolean) {
873
    }
874

875
    /**
876
     * @hidden @internal
877
     */
878
    @Input()
879
    public override get pinning() {
880
        return {};
157,735✔
881
    }
882
    public override set pinning(_value) {
883
    }
884

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

893
    public override set summaryPosition(_value: GridSummaryPosition) {
894
    }
895

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

904
    public override set summaryCalculationMode(_value: GridSummaryCalculationMode) {
905
    }
906

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

915
    public override set showSummaryOnCollapse(_value: boolean) {
916
    }
917

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

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

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

940
    public override set batchEditing(_val: boolean) {
941
    }
942

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

969
        });
970

971
        return selectedRowIds;
15✔
972
    }
973

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

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

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

1016
    }
1017

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

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

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

1053
    protected get allVisibleDimensions() {
1054
        const config = this._pivotConfiguration;
299✔
1055
        if (!config) return [];
299✔
1056
        const uniqueVisibleRowDims = this.visibleRowDimensions.filter(dim => !config.rows.find(configRow => configRow.memberName === dim.memberName));
337✔
1057
        const rows = (config.rows || []).concat(...uniqueVisibleRowDims);
295!
1058
        return rows.concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
848!
1059
    }
1060

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

1073
    protected get emptyBottomSize() {
1074
        return this.totalHeight - (<any>this.verticalScroll).scrollComponent.size;
5,261✔
1075
    }
1076

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

1092
    /** @hidden */
1093
    public override featureColumnsWidth() {
1094
        return this.pivotRowWidths || 0;
9,384✔
1095
    }
1096

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

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

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

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

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

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

1189
    /**
1190
     * @hidden @internal
1191
     */
1192
    public rowDimensionWidthToPixels(dim: IPivotDimension): number {
1193
        if (!dim?.width) {
86,479✔
1194
            return MINIMUM_COLUMN_WIDTH;
83,747✔
1195
        }
1196
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
2,732✔
1197
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
2,732✔
1198
        if (isPercent) {
2,732✔
1199
            return Math.round(parseFloat(dim.width) / 100 * this.calcWidth);
605✔
1200
        } else if (isAuto) {
2,127✔
1201
            return dim.autoWidth;
110✔
1202
        } else {
1203
            return parseInt(dim.width, 10);
2,017✔
1204
        }
1205
    }
1206

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

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

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

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

1234
    /** @hidden @internal */
1235
    public get pivotPinnedEndWidth() {
1236
        return !this._init ? this.pinnedEndWidth : 0;
6,822✔
1237
    }
1238

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

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

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

1254
    public get visibleRowDimensions() {
1255
        return this._visibleRowDimensions || this.rowDimensions;
41,865!
1256
    }
1257

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

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

1268
    /** @hidden @internal */
1269
    public get values() {
1270
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
735,767✔
1271
    }
1272

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

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

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

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

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

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

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

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

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

1334
    public override set totalRecords(_total: number) {
1335
    }
1336

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

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

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

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

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

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

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

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

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

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

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

1407
    /**
1408
     * @hidden @internal
1409
     */
1410
    public override get pinnedRowHeight() {
1411
        return;
2,916✔
1412
    }
1413

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

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

1428
    /**
1429
     * @hidden @internal
1430
     */
1431
    public override get hasMovableColumns(): boolean {
1432
        return;
41,228✔
1433
    }
1434

1435
    /**
1436
     * @hidden @internal
1437
     */
1438
    public override get pinnedDataView(): any[] {
1439
        return [];
11,513✔
1440
    }
1441

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

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

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

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

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

1473
    /**
1474
     * @hidden @internal
1475
     */
1476
    public override clearSearch() { }
1477

1478
    /**
1479
    * @hidden @internal
1480
    */
1481
    public override refreshSearch(_updateActiveInfo?: boolean, _endEdit = true): number {
99✔
1482
        return 0;
507✔
1483
    }
1484

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

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

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

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

1515
    /**
1516
    * @hidden @internal
1517
    */
1518
    public override getPinnedStartWidth(takeHidden = false) {
624✔
1519
        return super.getPinnedStartWidth(takeHidden);
3,025✔
1520
    }
1521

1522
    /**
1523
     * @hidden @internal
1524
     */
1525
    public override get totalHeight() {
1526
        return this.calcHeight;
10,636✔
1527
    }
1528

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

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

1564
    /**
1565
    * @hidden @internal
1566
    */
1567
    public override setupColumns() {
1568
        super.setupColumns();
265✔
1569
    }
1570

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

1579
        super.dataRebinding(event);
377✔
1580
    }
1581

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1969
    /** @hidden @internal */
1970
    public get hasHorizontalLayout() {
1971
        return this.pivotUI.rowLayout === PivotRowLayoutType.Horizontal;
78,346✔
1972
    }
1973

1974
    /**
1975
    * @hidden
1976
    */
1977
    public get hasMultipleValues() {
1978
        return this.values.length > 1;
185,865✔
1979
    }
1980

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

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

1999
    /** @hidden @internal */
2000
    public override get activeDescendant(): string | undefined {
2001
        if (this.navigation.isRowHeaderActive || this.navigation.isRowDimensionHeaderActive) {
4,548✔
2002
            return;
208✔
2003
        }
2004
        return super.activeDescendant;
4,340✔
2005
    }
2006

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

2014
        const rowDimensions = this.rowDimensionContentCollection.length > 0 ?
177✔
2015
            this.rowDimensionContentCollection.toArray() :
2016
            this.rowDimensionMrlComponent.rowDimensionContentCollection.toArray();
2017

2018
        const rowDimensionContentActive = rowDimensions.find(rd => rd && rd.headerGroups?.some(hg => hg.active));
624✔
2019
        const activeHeader = rowDimensionContentActive?.headerGroups.toArray().find(hg => hg.active);
177✔
2020

2021
        return activeHeader ? `${this.id}_${activeHeader.title}` : null;
177✔
2022
    }
2023

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

2050
    protected override buildDataView(data: any[]) {
2051
        this._dataView = data;
408✔
2052
    }
2053

2054
    /**
2055
     * @hidden @internal
2056
     */
2057
    protected override getDataBasedBodyHeight(): number {
2058
        const dvl = this.dataView?.length || 0;
83!
2059
        return dvl < this._defaultTargetRecordNumber ? 0 : this.defaultTargetBodyHeight;
83✔
2060
    }
2061

2062
    protected override horizontalScrollHandler(event) {
2063
        const scrollLeft = event.target.scrollLeft;
2✔
2064
        this.theadRow.headerContainers.forEach(headerForOf => {
2✔
2065
            headerForOf.onHScroll(scrollLeft);
4✔
2066
        });
2067
        super.horizontalScrollHandler(event);
2✔
2068
    }
2069

2070
    protected override verticalScrollHandler(event) {
2071
        this.verticalRowDimScrollContainers.forEach(x => {
×
2072
            x.onScroll(event);
×
2073
        });
2074
        super.verticalScrollHandler(event);
×
2075
    }
2076

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

2123
        this.updateColumns(columns);
263✔
2124
        this.pipeTrigger++;
263✔
2125
        this.reflow();
263✔
2126
    }
2127

2128
    protected generateDimensionColumns(): IgxColumnComponent[] {
2129
        const columns = [];
299✔
2130
        this.allVisibleDimensions.forEach((dim) => {
299✔
2131
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
848✔
2132
            ref.instance.field = dim.memberName;
848✔
2133
            ref.instance.header = dim.displayName || dim.memberName;
848✔
2134
            ref.instance.headerTemplate = this.rowDimensionHeaderTemplate;
848✔
2135
            ref.instance.resizable = this.rowDimensionResizing;
848✔
2136
            ref.instance.sortable = dim.sortable === undefined ? true : dim.sortable;
848!
2137
            ref.instance.width = this.rowDimensionWidth(dim);
848✔
2138
            ref.instance.filteringIgnoreCase = false;
848✔
2139
            ref.changeDetectorRef.detectChanges();
848✔
2140
            columns.push(ref.instance);
848✔
2141
        });
2142
        return columns;
299✔
2143
    }
2144

2145
    protected override calculateGridSizes(recalcFeatureWidth = true) {
536✔
2146
        super.calculateGridSizes(recalcFeatureWidth);
536✔
2147
        if (this.hasDimensionsToAutosize) {
536✔
2148
            this.cdr.detectChanges();
2✔
2149
            this.zone.onStable.pipe(first()).subscribe(() => {
2✔
2150
                requestAnimationFrame(() => {
2✔
2151
                    this.autoSizeDimensionsInView();
2✔
2152
                });
2153
            });
2154
        }
2155
    }
2156

2157
    protected getContentCollection(dimenstion: IPivotDimension) {
2158
        let contentCollection;
2159
        if (this.hasHorizontalLayout) {
3!
2160
            const allMrlContents = this.rowDimensionMrlRowsCollection.map(mrlRow => mrlRow.contentCells.toArray()).flat();
×
2161
            contentCollection = allMrlContents.filter(cell => cell.rootDimension === dimenstion);
×
2162
        } else {
2163
            contentCollection = this.rowDimensionContentCollection.toArray();
3✔
2164
        }
2165
        return contentCollection;
3✔
2166
    }
2167

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

2192
        if (this.isColumnWidthSum) {
1!
2193
            this.calcWidth = this.getColumnWidthSum();
×
2194
        }
2195
    }
2196

2197
    /** @hidden @internal */
2198
    public get hasDimensionsToAutosize() {
2199
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
794✔
2200
    }
2201

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

2233
                if (value.aggregate?.key?.toLowerCase() === 'count' && (columnDataType === GridColumnDataType.Currency || columnDataType == GridColumnDataType.Percent)) {
21!
2234
                    columnDataType = GridColumnDataType.Number;
×
2235
                }
2236

2237
                ref.instance.header = value.displayName;
21✔
2238
                ref.instance.field = value.member;
21✔
2239
                ref.instance.parent = parent;
21✔
2240
                ref.instance.sortable = true;
21✔
2241
                ref.instance.dataType = columnDataType;
21✔
2242
                ref.instance.formatter = value.formatter;
21✔
2243
                columns.push(ref.instance);
21✔
2244
            });
2245
            return columns;
20✔
2246
        }
2247
        const currentFields = fields;
307✔
2248
        currentFields.forEach((value) => {
307✔
2249
            let shouldGenerate = true;
1,097✔
2250
            if (data.length === 0) {
1,097!
2251
                shouldGenerate = false;
×
2252
            }
2253
            if (shouldGenerate && (value.children == null || value.children.length === 0 || value.children.size === 0)) {
1,097✔
2254
                const col = this.createColumnForDimension(value, data, parent, this.hasMultipleValues);
1,033✔
2255

2256
                if (!this.hasMultipleValues && this.values.length > 0) {
1,033✔
2257
                    PivotUtil.updateColumnTypeByAggregator([col], this.values[0], true);
160✔
2258
                }
2259

2260
                columns.push(col);
1,033✔
2261
                if (this.hasMultipleValues) {
1,033✔
2262
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
862✔
2263

2264
                    measureChildren.forEach((child, index) => {
862✔
2265
                        const pivotValue = this.values[index];
1,729✔
2266
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
1,729✔
2267
                    });
2268

2269
                    col.children.reset(measureChildren);
862✔
2270
                    columns = columns.concat(measureChildren);
862✔
2271
                }
2272

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

2291
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2292
                        sibling.children.reset(measureChildren);
20✔
2293
                        columns = columns.concat(measureChildren);
20✔
2294
                    }
2295

2296
                } else {
2297
                    col.children.reset(filteredChildren);
1✔
2298
                    columns = columns.concat(children);
1✔
2299
                    if (value.dimension.childLevel) {
1✔
2300
                        const sibling = this.createColumnForDimension(value, data, parent, false);
1✔
2301
                        columns.push(sibling);
1✔
2302
                    }
2303
                }
2304
            }
2305
        });
2306

2307
        return columns;
307✔
2308
    }
2309

2310

2311
    protected generateConfig() {
2312
        if (!this.data) return;
1!
2313

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

2371
    protected createColumnForDimension(value: any, data: any, parent: ColumnType, isGroup: boolean) {
2372
        const key = value.value;
1,118✔
2373
        const ref = isGroup ?
1,118✔
2374
            createComponent(IgxColumnGroupComponent, { environmentInjector: this.envInjector, elementInjector: this.injector }) :
2375
            createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2376
        ref.instance.header = parent != null ? key.split(parent.header + this.pivotKeys.columnDimensionSeparator)[1] : key;
1,118✔
2377
        ref.instance.field = key;
1,118✔
2378
        ref.instance.parent = parent;
1,118✔
2379
        if (value.dimension.width) {
1,118!
2380
            ref.instance.width = value.dimension.width;
×
2381
        }
2382
        const valueDefinition = this.values[0];
1,118✔
2383
        ref.instance.dataType = valueDefinition?.dataType || this.resolveDataTypes(data[0][valueDefinition?.member]);
1,118✔
2384
        ref.instance.formatter = valueDefinition?.formatter;
1,118✔
2385
        ref.instance.sortable = true;
1,118✔
2386
        ref.changeDetectorRef.detectChanges();
1,118✔
2387
        return ref.instance;
1,118✔
2388
    }
2389

2390
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2391
        if (dim.width) {
×
2392
            return dim.width;
×
2393
        }
2394
        return this.minColumnWidth + 'px';
×
2395
    }
2396

2397
    protected getMeasureChildren(data, parent, hidden, parentWidth) {
2398
        const cols = [];
945✔
2399
        const count = this.values.length;
945✔
2400
        const childWidth = parseInt(parentWidth, 10) / count;
945✔
2401
        const isPercent = parentWidth && parentWidth.indexOf('%') !== -1;
945!
2402
        const isAuto = parentWidth && parentWidth.indexOf('auto') !== -1;
945!
2403
        this.values.forEach(val => {
945✔
2404
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
1,895✔
2405
            ref.instance.header = val.displayName || val.member;
1,895✔
2406
            ref.instance.field = parent.field + this.pivotKeys.columnDimensionSeparator + val.member;
1,895✔
2407
            ref.instance.parent = parent;
1,895✔
2408
            if (parentWidth) {
1,895!
2409
                ref.instance.width = isAuto ? 'auto' : isPercent ? childWidth + '%' : childWidth + 'px';
×
2410
            }
2411
            ref.instance.hidden = hidden;
1,895✔
2412
            ref.instance.sortable = this._sortableColumns;
1,895✔
2413
            ref.instance.dataType = val.dataType || this.resolveDataTypes(data[0][val.member]);
1,895✔
2414
            ref.instance.formatter = val.formatter;
1,895✔
2415
            ref.changeDetectorRef.detectChanges();
1,895✔
2416
            cols.push(ref.instance);
1,895✔
2417
        });
2418
        return cols;
945✔
2419
    }
2420

2421
    /**
2422
    * @hidden @internal
2423
    */
2424
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2425
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2426

2427
    /**
2428
     * Gets/Sets a custom template when pivot grid is empty.
2429
     *
2430
     * @example
2431
     * ```html
2432
     * <igx-pivot-grid [emptyPivotGridTemplate]="myTemplate"><igx-pivot-grid>
2433
     * ```
2434
     */
2435
    @Input()
2436
    public emptyPivotGridTemplate: TemplateRef<void>;
2437

2438
    /**
2439
    * @hidden @internal
2440
    */
2441
    public override get template(): TemplateRef<any> {
2442
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
2,274✔
2443
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
2,274✔
2444
            // no enabled values and dimensions
2445
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
55✔
2446
        }
2447
        return super.template;
2,219✔
2448
    }
2449

2450
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2451
        const dimensions = PivotUtil.flatten(this.allDimensions);
173✔
2452
        dimensions.forEach(dim => {
173✔
2453
            this.dimensionInit.emit(dim);
616✔
2454
        });
2455
        const values = pivotConfig?.values;
173✔
2456
        values?.forEach(val => {
173✔
2457
            this.valueInit.emit(val);
308✔
2458
        });
2459
    }
2460

2461
    protected rowDimensionByName(memberName: string) {
2462
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2463
    }
2464

2465
    protected calculateResizerTop() {
2466
        return this.pivotUI.showRowHeaders ?
18✔
2467
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
8!
2468
            this.theadRow.nativeElement.offsetHeight;
2469
    }
2470

2471
    protected override updateDefaultRowHeight() {
2472
        super.updateDefaultRowHeight();
210✔
2473
        if (this.hasHorizontalLayout) {
210✔
2474
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2475
            this.regroupTrigger++;
12✔
2476
        }
2477
    }
2478

2479
    /**
2480
     * @hidden @internal
2481
     */
2482
    public createRow(index: number, data?: any): RowType {
2483
        let row: RowType;
2484

2485
        const dataIndex = this._getDataViewIndex(index);
×
2486
        const rec = data ?? this.dataView[dataIndex];
×
2487

2488

2489
        if (!row && rec) {
×
2490
            row = new IgxPivotGridRow(this, index, rec);
×
2491
        }
2492
        return row;
×
2493
    }
2494
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc