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

IgniteUI / igniteui-angular / 26023601418

18 May 2026 08:57AM UTC coverage: 4.854% (-85.3%) from 90.174%
26023601418

Pull #17281

github

web-flow
Merge e7ce7a18e into 5a85df190
Pull Request #17281: feat: Added virtual scroll component and sample implementation

400 of 17347 branches covered (2.31%)

Branch coverage included in aggregate %.

63 of 222 new or added lines in 4 files covered. (28.38%)

27932 existing lines in 341 files now uncovered.

2022 of 32547 relevant lines covered (6.21%)

0.72 hits per line

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

0.39
/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 */
UNCOV
157
    public override readonly gridAPI = inject<GridBaseAPIService<IgxGridBaseDirective & GridType>>(GridBaseAPIService);
×
158
    /* blazorSuppress */
UNCOV
159
    public override navigation = inject(IgxPivotGridNavigationService);
×
UNCOV
160
    protected override colResizingService = inject(IgxPivotColumnResizingService);
×
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()
UNCOV
174
    public dimensionsChange = new EventEmitter<IDimensionsChange>();
×
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()
UNCOV
186
    public pivotConfigurationChange = new EventEmitter<IPivotConfigurationChangedEventArgs>();
×
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()
UNCOV
200
    public dimensionInit = new EventEmitter<IPivotDimension>();
×
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()
UNCOV
213
    public valueInit = new EventEmitter<IPivotValue>();
×
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()
UNCOV
226
    public dimensionsSortingExpressionsChange = new EventEmitter<ISortingExpression[]>();
×
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()
UNCOV
240
    public valuesChange = new EventEmitter<IValuesChange>();
×
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() {
UNCOV
252
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
×
UNCOV
253
        const dimensionsSortingExpressions = PivotSortUtil.generateDimensionSortingExpressions(allEnabledDimensions);
×
UNCOV
254
        return dimensionsSortingExpressions;
×
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) {
UNCOV
299
        this._pivotConfiguration = value;
×
UNCOV
300
        this.emitInitEvents(this._pivotConfiguration);
×
UNCOV
301
        this.filteringExpressionsTree = PivotUtil.buildExpressionTree(value);
×
UNCOV
302
        if (!this._init) {
×
UNCOV
303
            this.setupColumns();
×
304
        }
UNCOV
305
        this.notifyChanges(true);
×
306
    }
307

308
    /* mustSetInCodePlatforms: WebComponents;Blazor */
309
    public get pivotConfiguration() {
UNCOV
310
        return this._pivotConfiguration || { rows: null, columns: null, values: null, filters: null };
×
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 })
UNCOV
324
    public autoGenerateConfig = false;
×
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) {
UNCOV
337
        this._pivotUI = Object.assign(this._pivotUI, value || {});
×
UNCOV
338
        this.pipeTrigger++;
×
UNCOV
339
        this.notifyChanges(true);
×
340
    }
341

342
    public get pivotUI() {
UNCOV
343
        return this._pivotUI;
×
344
    }
345

346
    /**
347
     * @hidden @internal
348
     */
349
    @HostBinding('attr.role')
UNCOV
350
    public role = 'grid';
×
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() {
UNCOV
364
        return this._superCompactMode;
×
365
    }
366

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

371
    /** @hidden @internal */
372
    public override get gridSize() {
UNCOV
373
        if (this.superCompactMode) {
×
UNCOV
374
            return ɵSize.Small;
×
375
        }
UNCOV
376
        return super.gridSize;
×
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 {
UNCOV
391
        return this._pivotValueCloneStrategy;
×
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() {
UNCOV
446
        if (this.superCompactMode) {
×
UNCOV
447
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
×
448
        } else {
UNCOV
449
            return MINIMUM_COLUMN_WIDTH;
×
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()
UNCOV
475
    public override autoGenerateExclude: string[] = [];
×
476

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

634
    /**
635
     * @hidden @internal
636
     */
UNCOV
637
    public rowDimensionResizing = true;
×
638

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

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

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

673
    public set defaultExpandState(val: boolean) {
UNCOV
674
        this._defaultExpandState = val;
×
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
     */
UNCOV
703
    public override autoGenerate = true;
×
704

705
    /**
706
     * @hidden @internal
707
     */
708
    public override get actionStrip() {
UNCOV
709
        return undefined as any;
×
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
     */
UNCOV
726
    public override moving = false;
×
727

728
    /**
729
     * @hidden @internal
730
     */
UNCOV
731
    public override toolbarExporting = new EventEmitter<IGridToolbarExportEventArgs>();
×
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() {
UNCOV
772
        return false;
×
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[] {
UNCOV
804
        return [];
×
805
    }
806

807
    /**
808
    * @hidden @internal
809
    */
810
    public override get unpinnedColumns(): IgxColumnComponent[] {
UNCOV
811
        return super.unpinnedColumns;
×
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() {
UNCOV
825
        return super.unpinnedWidth;
×
826
    }
827

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

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

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

846
    /**
847
     * @hidden @internal
848
     */
849
    public override get transactions(): TransactionService<Transaction, State> {
UNCOV
850
        return this._transactions;
×
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 {
UNCOV
871
        return;
×
872
    }
873

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

877
    /**
878
     * @hidden @internal
879
     */
880
    @Input()
881
    public override get pinning() {
UNCOV
882
        return {};
×
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[] {
UNCOV
947
        if (this.selectionService.getSelectedRows().length === 0) {
×
UNCOV
948
            return [];
×
949
        }
UNCOV
950
        const selectedRowIds = [];
×
UNCOV
951
        this.dataView.forEach(record => {
×
UNCOV
952
            const prev = [];
×
UNCOV
953
            for (const dim of this.rowDimensions) {
×
UNCOV
954
                let currDim = dim;
×
UNCOV
955
                let shouldBreak = false;
×
UNCOV
956
                do {
×
UNCOV
957
                    const key = PivotUtil.getRecordKey(record, currDim);
×
UNCOV
958
                    if (this.selectionService.isPivotRowSelected(key) && !selectedRowIds.find(x => x === record)) {
×
UNCOV
959
                        selectedRowIds.push(record);
×
UNCOV
960
                        shouldBreak = true;
×
UNCOV
961
                        break;
×
962
                    }
UNCOV
963
                    currDim = currDim.childLevel;
×
964
                } while (currDim);
UNCOV
965
                prev.push(dim);
×
UNCOV
966
                if (shouldBreak) {
×
UNCOV
967
                    break;
×
968
                }
969
            }
970

971
        });
972

UNCOV
973
        return selectedRowIds;
×
974
    }
975

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

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

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

1018
    }
1019

1020
    /**
1021
     * @hidden @internal
1022
     */
1023
    public ngOnChanges(changes: SimpleChanges) {
UNCOV
1024
        if (changes.superCompactMode && !changes.superCompactMode.isFirstChange()) {
×
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) {
×
UNCOV
1034
        if (regenerateColumns) {
×
UNCOV
1035
            this.setupColumns();
×
1036
        }
UNCOV
1037
        this.pipeTrigger++;
×
UNCOV
1038
        this.cdr.detectChanges();
×
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() {
UNCOV
1050
        const config = this._pivotConfiguration;
×
UNCOV
1051
        if (!config) return [];
×
UNCOV
1052
        return (config.rows || []).concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
×
1053
    }
1054

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

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

1075
    protected get emptyBottomSize() {
UNCOV
1076
        return this.totalHeight - (<any>this.verticalScroll).scrollComponent.size;
×
1077
    }
1078

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

1094
    /** @hidden */
1095
    public override featureColumnsWidth() {
UNCOV
1096
        return this.pivotRowWidths || 0;
×
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 {
UNCOV
1113
        return this.p_id;
×
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) {
UNCOV
1130
        this._data = value || [];
×
UNCOV
1131
        if (!this._init) {
×
UNCOV
1132
            if (this.autoGenerateConfig) {
×
UNCOV
1133
                this.generateConfig();
×
1134
            }
UNCOV
1135
            this.setupColumns();
×
UNCOV
1136
            this.reflow();
×
1137
        }
UNCOV
1138
        this.cdr.markForCheck();
×
UNCOV
1139
        if (this.height === null || this.height.indexOf('%') !== -1) {
×
1140
            // If the height will change based on how much data there is, recalculate sizes in igxForOf.
UNCOV
1141
            this.notifyChanges(true);
×
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 {
UNCOV
1154
        return this._data;
×
1155
    }
1156

1157
    /**
1158
     * @hidden
1159
     */
1160
    public getContext(rowData, rowIndex): any {
UNCOV
1161
        return {
×
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() {
UNCOV
1175
        return this.visibleRowDimensions.length ? this.visibleRowDimensions.reduce((accumulator, dim) => accumulator + this.rowDimensionWidthToPixels(dim), 0) :
×
1176
            this.rowDimensionWidthToPixels(this.emptyRowDimension);
1177
    }
1178

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

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

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

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

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

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

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

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

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

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

1256
    public get visibleRowDimensions() {
UNCOV
1257
        return this._visibleRowDimensions || this.rowDimensions;
×
1258
    }
1259

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

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

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

1275
    public toggleColumn(col: IgxColumnComponent) {
UNCOV
1276
        const state = this.columnGroupStates.get(col.field);
×
UNCOV
1277
        const newState = !state;
×
UNCOV
1278
        this.columnGroupStates.set(col.field, newState);
×
UNCOV
1279
        this.toggleRowGroup(col, newState);
×
UNCOV
1280
        this.reflow();
×
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[] {
UNCOV
1325
        return;
×
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() {
UNCOV
1413
        return;
×
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 {
UNCOV
1427
        return;
×
1428
    }
1429

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

1437
    /**
1438
     * @hidden @internal
1439
     */
1440
    public override get pinnedDataView(): any[] {
UNCOV
1441
        return [];
×
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 {
×
UNCOV
1484
        return 0;
×
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) {
×
UNCOV
1521
        return super.getPinnedStartWidth(takeHidden);
×
1522
    }
1523

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

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

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

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

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

UNCOV
1581
        super.dataRebinding(event);
×
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) {
UNCOV
1596
        if (this.getDimensionType(dimension) === PivotDimensionType.Row) {
×
UNCOV
1597
            const relatedDims: string[] = PivotUtil.flatten([dimension]).map((x: IPivotDimension) => x.memberName);
×
UNCOV
1598
            const contentCollection = this.getContentCollection(dimension);
×
UNCOV
1599
            const content = contentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
×
UNCOV
1600
            const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
×
UNCOV
1601
            if (this.pivotUI.showRowHeaders) {
×
1602
                const dimensionHeader = this.theadRow.rowDimensionHeaders.find(x => x.column.field === dimension.memberName);
×
1603
                headers.push(dimensionHeader);
×
1604
            }
UNCOV
1605
            const autoWidth = this.getLargesContentWidth(headers);
×
UNCOV
1606
            if (dimension.width === "auto") {
×
1607
                dimension.autoWidth = parseFloat(autoWidth);
×
1608
            } else {
UNCOV
1609
                dimension.width = autoWidth;
×
1610
            }
UNCOV
1611
            this.pipeTrigger++;
×
UNCOV
1612
            this.cdr.detectChanges();
×
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) {
UNCOV
1629
        const targetCollection = this.getDimensionsByType(targetCollectionType);
×
UNCOV
1630
        if (index !== undefined) {
×
UNCOV
1631
            targetCollection.splice(index, 0, dimension);
×
1632
        } else {
UNCOV
1633
            targetCollection.push(dimension);
×
1634
        }
UNCOV
1635
        if (targetCollectionType === PivotDimensionType.Column) {
×
UNCOV
1636
            this.setupColumns();
×
1637
        }
UNCOV
1638
        this.pipeTrigger++;
×
UNCOV
1639
        this.dimensionsChange.emit({ dimensions: targetCollection, dimensionCollectionType: targetCollectionType });
×
UNCOV
1640
        if (targetCollectionType === PivotDimensionType.Filter) {
×
UNCOV
1641
            this.dimensionDataColumns = this.generateDimensionColumns();
×
UNCOV
1642
            this.reflow();
×
1643
        }
UNCOV
1644
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
×
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) {
UNCOV
1660
        const prevCollectionType = this.getDimensionType(dimension);
×
UNCOV
1661
        if (prevCollectionType === null) return;
×
1662
        // remove from old collection
UNCOV
1663
        this._removeDimensionInternal(dimension);
×
1664
        // add to target
UNCOV
1665
        this.insertDimensionAt(dimension, targetCollectionType, index);
×
1666

UNCOV
1667
        if (prevCollectionType === PivotDimensionType.Column) {
×
UNCOV
1668
            this.setupColumns();
×
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) {
UNCOV
1684
        const prevCollectionType = this.getDimensionType(dimension);
×
UNCOV
1685
        this._removeDimensionInternal(dimension);
×
UNCOV
1686
        if (prevCollectionType === PivotDimensionType.Column) {
×
UNCOV
1687
            this.setupColumns();
×
1688
        }
UNCOV
1689
        if (prevCollectionType === PivotDimensionType.Filter) {
×
UNCOV
1690
            this.reflow();
×
1691
        }
UNCOV
1692
        this.pipeTrigger++;
×
UNCOV
1693
        this.cdr.detectChanges();
×
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) {
UNCOV
1707
        const dimType = this.getDimensionType(dimension);
×
UNCOV
1708
        if (dimType === null) return;
×
UNCOV
1709
        const collection = this.getDimensionsByType(dimType);
×
UNCOV
1710
        dimension.enabled = !dimension.enabled;
×
UNCOV
1711
        if (dimType === PivotDimensionType.Column) {
×
UNCOV
1712
            this.setupColumns();
×
1713
        }
UNCOV
1714
        if (!dimension.enabled && dimension.filter) {
×
UNCOV
1715
            this.filteringService.clearFilter(dimension.memberName);
×
1716
        }
UNCOV
1717
        this.pipeTrigger++;
×
UNCOV
1718
        this.dimensionsChange.emit({ dimensions: collection, dimensionCollectionType: dimType });
×
UNCOV
1719
        this.cdr.detectChanges();
×
UNCOV
1720
        if (dimType === PivotDimensionType.Filter) {
×
UNCOV
1721
            this.reflow();
×
1722
        }
UNCOV
1723
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
×
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) {
UNCOV
1738
        if (!this.pivotConfiguration.values) {
×
UNCOV
1739
            this.pivotConfiguration.values = [];
×
1740
        }
UNCOV
1741
        const values = this.pivotConfiguration.values;
×
UNCOV
1742
        if (index !== undefined) {
×
UNCOV
1743
            values.splice(index, 0, value);
×
1744
        } else {
UNCOV
1745
            values.push(value);
×
1746
        }
UNCOV
1747
        this.setupColumns();
×
UNCOV
1748
        this.pipeTrigger++;
×
UNCOV
1749
        this.cdr.detectChanges();
×
UNCOV
1750
        this.valuesChange.emit({ values });
×
UNCOV
1751
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
×
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) {
UNCOV
1766
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
×
1767
        // remove from old index
UNCOV
1768
        this.removeValue(value);
×
1769
        // add to new
UNCOV
1770
        this.insertValueAt(value, index);
×
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,) {
UNCOV
1785
        const values = this.pivotConfiguration.values;
×
UNCOV
1786
        const currentIndex = values.indexOf(value);
×
UNCOV
1787
        if (currentIndex !== -1) {
×
UNCOV
1788
            values.splice(currentIndex, 1);
×
UNCOV
1789
            this.setupColumns();
×
UNCOV
1790
            this.pipeTrigger++;
×
UNCOV
1791
            this.valuesChange.emit({ values });
×
UNCOV
1792
            this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
×
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) {
UNCOV
1807
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
×
UNCOV
1808
        value.enabled = !value.enabled;
×
UNCOV
1809
        this.setupColumns();
×
UNCOV
1810
        this.pipeTrigger++;
×
UNCOV
1811
        this.valuesChange.emit({ values: this.pivotConfiguration.values });
×
UNCOV
1812
        this.reflow();
×
UNCOV
1813
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
×
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) {
UNCOV
1825
        const dimensionType = this.getDimensionType(dimension);
×
UNCOV
1826
        dimension.sortDirection = sortDirection;
×
1827
        // apply same sort direction to children.
UNCOV
1828
        let dim = dimension;
×
UNCOV
1829
        if (this.pivotUI.rowLayout === PivotRowLayoutType.Vertical) {
×
UNCOV
1830
            while (dim.childLevel) {
×
UNCOV
1831
                dim.childLevel.sortDirection = dimension.sortDirection;
×
UNCOV
1832
                dim = dim.childLevel;
×
1833
            }
1834
        }
1835

UNCOV
1836
        this.pipeTrigger++;
×
UNCOV
1837
        this.dimensionsSortingExpressionsChange.emit(this.dimensionsSortingExpressions);
×
UNCOV
1838
        if (dimensionType === PivotDimensionType.Column) {
×
UNCOV
1839
            this.setupColumns();
×
1840
        }
UNCOV
1841
        this.cdr.detectChanges();
×
UNCOV
1842
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
×
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) {
UNCOV
1859
        this.filteringService.filter(dimension.memberName, value, conditionOrExpressionTree);
×
UNCOV
1860
        const dimensionType = this.getDimensionType(dimension);
×
UNCOV
1861
        if (dimensionType === PivotDimensionType.Column) {
×
UNCOV
1862
            this.setupColumns();
×
1863
        }
UNCOV
1864
        this.cdr.detectChanges();
×
1865
    }
1866

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

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

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

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

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

1934
    protected getDimensionType(dimension: IPivotDimension): PivotDimensionType {
UNCOV
1935
        return PivotUtil.flatten(this.pivotConfiguration.rows).indexOf(dimension) !== -1 ? PivotDimensionType.Row :
×
1936
            PivotUtil.flatten(this.pivotConfiguration.columns).indexOf(dimension) !== -1 ? PivotDimensionType.Column :
×
1937
                (!!this.pivotConfiguration.filters && PivotUtil.flatten(this.pivotConfiguration.filters).indexOf(dimension) !== -1) ?
×
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 {
UNCOV
1947
        const largest = new Map<number, number>();
×
UNCOV
1948
        if (contents.length > 0) {
×
UNCOV
1949
            const cellsContentWidths = [];
×
UNCOV
1950
            contents.forEach((elem) => {
×
UNCOV
1951
                elem instanceof IgxPivotRowHeaderGroupComponent ?
×
1952
                    cellsContentWidths.push(this.getPivotRowHeaderContentWidth(elem)) :
1953
                    cellsContentWidths.push(this.getHeaderCellWidth(elem.nativeElement).width);
1954
            });
UNCOV
1955
            const index = cellsContentWidths.indexOf(Math.max(...cellsContentWidths));
×
UNCOV
1956
            const cellStyle = this.document.defaultView.getComputedStyle(contents[index].nativeElement);
×
UNCOV
1957
            const cellPadding = parseFloat(cellStyle.paddingLeft) + parseFloat(cellStyle.paddingRight) +
×
1958
                parseFloat(cellStyle.borderLeftWidth) + parseFloat(cellStyle.borderRightWidth);
UNCOV
1959
            largest.set(Math.max(...cellsContentWidths), cellPadding);
×
1960
        }
UNCOV
1961
        const largestCell = Math.max(...Array.from(largest.keys()));
×
UNCOV
1962
        const width = Math.ceil(largestCell + largest.get(largestCell));
×
1963

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

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

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

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

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

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

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

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

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

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

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

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

2056
    protected override onContentSizeChange() {
UNCOV
2057
        super.onContentSizeChange();
×
UNCOV
2058
        this.updateDefaultRowHeight();
×
2059
    }
2060

2061
    /**
2062
     * @hidden @internal
2063
     */
2064
    protected override getDataBasedBodyHeight(): number {
UNCOV
2065
        const dvl = this.dataView?.length || 0;
×
UNCOV
2066
        return dvl < this._defaultTargetRecordNumber ? 0 : this.defaultTargetBodyHeight;
×
2067
    }
2068

2069
    protected override horizontalScrollHandler(event) {
UNCOV
2070
        const scrollLeft = event.target.scrollLeft;
×
UNCOV
2071
        this.theadRow.headerContainers.forEach(headerForOf => {
×
UNCOV
2072
            headerForOf.onHScroll(scrollLeft);
×
2073
        });
UNCOV
2074
        super.horizontalScrollHandler(event);
×
2075
    }
2076

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

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

UNCOV
2130
        this.updateColumns(columns);
×
UNCOV
2131
        this.pipeTrigger++;
×
UNCOV
2132
        this.reflow();
×
2133
    }
2134

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

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

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

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

UNCOV
2199
        if (this.isColumnWidthSum) {
×
2200
            this.calcWidth = this.getColumnWidthSum();
×
2201
        }
2202
    }
2203

2204
    /** @hidden @internal */
2205
    public get hasDimensionsToAutosize() {
UNCOV
2206
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
×
2207
    }
2208

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

UNCOV
2240
                if (value.aggregate?.key?.toLowerCase() === 'count' && (columnDataType === GridColumnDataType.Currency || columnDataType == GridColumnDataType.Percent)) {
×
2241
                    columnDataType = GridColumnDataType.Number;
×
2242
                }
2243

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

UNCOV
2263
                if (!this.hasMultipleValues && this.values.length > 0) {
×
UNCOV
2264
                    PivotUtil.updateColumnTypeByAggregator([col], this.values[0], true);
×
2265
                }
2266

UNCOV
2267
                columns.push(col);
×
UNCOV
2268
                if (this.hasMultipleValues) {
×
UNCOV
2269
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
×
2270

UNCOV
2271
                    measureChildren.forEach((child, index) => {
×
UNCOV
2272
                        const pivotValue = this.values[index];
×
UNCOV
2273
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
×
2274
                    });
2275

UNCOV
2276
                    col.children.reset(measureChildren);
×
UNCOV
2277
                    columns = columns.concat(measureChildren);
×
2278
                }
2279

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

UNCOV
2298
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
×
UNCOV
2299
                        sibling.children.reset(measureChildren);
×
UNCOV
2300
                        columns = columns.concat(measureChildren);
×
2301
                    }
2302

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

UNCOV
2314
        return columns;
×
2315
    }
2316

2317

2318
    protected generateConfig() {
UNCOV
2319
        if (!this.data) return;
×
2320

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

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

2397
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2398
        if (dim.width) {
×
2399
            return dim.width;
×
2400
        }
2401
        return this.minColumnWidth + 'px';
×
2402
    }
2403

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

2428
    /**
2429
    * @hidden @internal
2430
    */
2431
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2432
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2433

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

2445
    /**
2446
    * @hidden @internal
2447
    */
2448
    public override get template(): TemplateRef<any> {
UNCOV
2449
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
×
UNCOV
2450
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
×
2451
            // no enabled values and dimensions
UNCOV
2452
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
×
2453
        }
UNCOV
2454
        return super.template;
×
2455
    }
2456

2457
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
UNCOV
2458
        const dimensions = PivotUtil.flatten(this.allDimensions);
×
UNCOV
2459
        dimensions.forEach(dim => {
×
UNCOV
2460
            this.dimensionInit.emit(dim);
×
2461
        });
UNCOV
2462
        const values = pivotConfig?.values;
×
UNCOV
2463
        values?.forEach(val => {
×
UNCOV
2464
            this.valueInit.emit(val);
×
2465
        });
2466
    }
2467

2468
    protected rowDimensionByName(memberName: string) {
2469
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2470
    }
2471

2472
    protected calculateResizerTop() {
UNCOV
2473
        return this.pivotUI.showRowHeaders ?
×
2474
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
×
2475
            this.theadRow.nativeElement.offsetHeight;
2476
    }
2477

2478
    protected override updateDefaultRowHeight() {
UNCOV
2479
        super.updateDefaultRowHeight();
×
UNCOV
2480
        if (this.hasHorizontalLayout) {
×
2481
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
UNCOV
2482
            this.regroupTrigger++;
×
2483
        } else {
UNCOV
2484
            this.pipeTrigger++;
×
2485
        }
2486
    }
2487

2488
    /**
2489
     * @hidden @internal
2490
     */
2491
    public createRow(index: number, data?: any): RowType {
2492
        let row: RowType;
2493

2494
        const dataIndex = this._getDataViewIndex(index);
×
2495
        const rec = data ?? this.dataView[dataIndex];
×
2496

2497

2498
        if (!row && rec) {
×
2499
            row = new IgxPivotGridRow(this, index, rec);
×
2500
        }
2501
        return row;
×
2502
    }
2503
}
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