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

IgniteUI / igniteui-angular / 23947656049

03 Apr 2026 01:21PM UTC coverage: 90.173% (+0.003%) from 90.17%
23947656049

Pull #16434

github

web-flow
Merge 0a0d453b4 into 2b5cc7a4c
Pull Request #16434: chore(*): Hide overridden members in inherited type.

14827 of 17266 branches covered (85.87%)

Branch coverage included in aggregate %.

29899 of 32334 relevant lines covered (92.47%)

34480.27 hits per line

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

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

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

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

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

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

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

188

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

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

215

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

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

242

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

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

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

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

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

284
    @Input()
285
    public rowDimensionHeaderTemplate: TemplateRef<IgxColumnTemplateContext>;
286

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

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

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

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

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

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

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

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

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

379

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

741

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

853

854

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

971
        });
972

973
        return selectedRowIds;
15✔
974
    }
975

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

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

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

1018
    }
1019

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2125
        this.updateColumns(columns);
273✔
2126
        this.pipeTrigger++;
273✔
2127
        this.reflow();
273✔
2128
    }
2129

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

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

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

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

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

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

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

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

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

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

2262
                columns.push(col);
1,103✔
2263
                if (this.hasMultipleValues) {
1,103✔
2264
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
932✔
2265

2266
                    measureChildren.forEach((child, index) => {
932✔
2267
                        const pivotValue = this.values[index];
1,869✔
2268
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
1,869✔
2269
                    });
2270

2271
                    col.children.reset(measureChildren);
932✔
2272
                    columns = columns.concat(measureChildren);
932✔
2273
                }
2274

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

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

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

2309
        return columns;
317✔
2310
    }
2311

2312

2313
    protected generateConfig() {
2314
        if (!this.data) return;
1!
2315

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

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

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

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

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

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

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

2452
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2453
        const dimensions = PivotUtil.flatten(this.allDimensions);
183✔
2454
        dimensions.forEach(dim => {
183✔
2455
            this.dimensionInit.emit(dim);
656✔
2456
        });
2457
        const values = pivotConfig?.values;
183✔
2458
        values?.forEach(val => {
183✔
2459
            this.valueInit.emit(val);
328✔
2460
        });
2461
    }
2462

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

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

2473
    protected override updateDefaultRowHeight() {
2474
        super.updateDefaultRowHeight();
513✔
2475
        if (this.hasHorizontalLayout) {
513✔
2476
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2477
            this.regroupTrigger++;
12✔
2478
        } else {
2479
            this.pipeTrigger++;
501✔
2480
        }
2481
    }
2482

2483
    /**
2484
     * @hidden @internal
2485
     */
2486
    public createRow(index: number, data?: any): RowType {
2487
        let row: RowType;
2488

2489
        const dataIndex = this._getDataViewIndex(index);
×
2490
        const rec = data ?? this.dataView[dataIndex];
×
2491

2492

2493
        if (!row && rec) {
×
2494
            row = new IgxPivotGridRow(this, index, rec);
×
2495
        }
2496
        return row;
×
2497
    }
2498
}
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