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

IgniteUI / igniteui-angular / 15896792945

26 Jun 2025 08:24AM UTC coverage: 91.411% (-0.03%) from 91.437%
15896792945

Pull #15925

github

web-flow
Merge pull request #15890 from IgniteUI/mkirova/fix-15794-master

fix(igxGrid): Adjust expandable cell styles.
Pull Request #15925: Mass Merge 20.0.x to master

13386 of 15716 branches covered (85.17%)

59 of 84 new or added lines in 13 files covered. (70.24%)

1 existing line in 1 file now uncovered.

27065 of 29608 relevant lines covered (91.41%)

36691.58 hits per line

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

89.4
/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.ts
1
import {
2
    AfterContentInit,
3
    AfterViewInit,
4
    ChangeDetectionStrategy,
5
    ChangeDetectorRef,
6
    Component,
7
    EventEmitter,
8
    ElementRef,
9
    HostBinding,
10
    Inject,
11
    Input,
12
    IterableDiffers,
13
    LOCALE_ID,
14
    NgZone,
15
    OnInit,
16
    Output,
17
    Optional,
18
    QueryList,
19
    TemplateRef,
20
    ViewChild,
21
    ViewChildren,
22
    ViewContainerRef,
23
    Injector,
24
    ContentChild,
25
    createComponent,
26
    EnvironmentInjector,
27
    CUSTOM_ELEMENTS_SCHEMA,
28
    booleanAttribute,
29
    OnChanges,
30
    SimpleChanges,
31
    DOCUMENT
32
} from '@angular/core';
33
import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common';
34

35
import { first, take, takeUntil} from 'rxjs/operators';
36
import { IgxGridBaseDirective } from '../grid-base.directive';
37
import { IgxFilteringService } from '../filtering/grid-filtering.service';
38
import { IgxGridSelectionService } from '../selection/selection.service';
39
import { IgxForOfSyncService, IgxForOfScrollSyncService } from '../../directives/for-of/for_of.sync.service';
40
import { ColumnType, GridType, IGX_GRID_BASE, IGX_GRID_SERVICE_BASE, IgxColumnTemplateContext, RowType } from '../common/grid.interface';
41
import { IgxGridCRUDService } from '../common/crud.service';
42
import { IgxGridSummaryService } from '../summaries/grid-summary.service';
43
import { DEFAULT_PIVOT_KEYS, IDimensionsChange, IgxPivotGridValueTemplateContext, IPivotConfiguration, IPivotConfigurationChangedEventArgs, IPivotDimension, IPivotValue, IValuesChange, PivotDimensionType, IPivotUISettings, PivotRowLayoutType, PivotSummaryPosition } from './pivot-grid.interface';
44
import { IgxPivotHeaderRowComponent } from './pivot-header-row.component';
45
import { IgxColumnGroupComponent } from '../columns/column-group.component';
46
import { IgxColumnComponent } from '../columns/column.component';
47
import { PivotUtil } from './pivot-util';
48
import { FilterMode, GridPagingMode, GridSummaryCalculationMode, GridSummaryPosition, Size } from '../common/enums';
49
import { WatchChanges } from '../watch-changes';
50
import { OverlaySettings } from '../../services/public_api';
51
import {
52
    IGridEditEventArgs,
53
    ICellPosition,
54
    IColumnMovingEndEventArgs, IColumnMovingEventArgs, IColumnMovingStartEventArgs,
55
    IColumnVisibilityChangedEventArgs,
56
    IGridEditDoneEventArgs,
57
    IGridToolbarExportEventArgs,
58
    IPinColumnCancellableEventArgs,
59
    IPinColumnEventArgs,
60
    IPinRowEventArgs,
61
    IRowDataCancelableEventArgs,
62
    IRowDataEventArgs,
63
    IRowDragEndEventArgs,
64
    IRowDragStartEventArgs
65
} from '../common/events';
66
import { IgxGridRowComponent } from '../grid/grid-row.component';
67
import { DropPosition } from '../moving/moving.service';
68
import { DimensionValuesFilteringStrategy, NoopPivotDimensionsStrategy } from '../../data-operations/pivot-strategy';
69
import { IgxGridExcelStyleFilteringComponent, IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleFilterOperationsTemplateDirective } from '../filtering/excel-style/excel-style-filtering.component';
70
import { IgxPivotGridNavigationService } from './pivot-grid-navigation.service';
71
import { IgxPivotColumnResizingService } from '../resizing/pivot-grid/pivot-resizing.service';
72
import { IgxFlatTransactionFactory, IgxOverlayService, State, Transaction, TransactionService } from '../../services/public_api';
73
import { cloneArray, PlatformUtil, resizeObservable } from '../../core/utils';
74
import { IgxPivotFilteringService } from './pivot-filtering.service';
75
import { DataUtil } from '../../data-operations/data-util';
76
import { IFilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree';
77
import { IgxGridTransaction } from '../common/types';
78
import { GridBaseAPIService } from '../api.service';
79
import { IForOfDataChangingEventArgs, IgxGridForOfDirective } from '../../directives/for-of/for_of.directive';
80
import { IgxPivotRowDimensionContentComponent } from './pivot-row-dimension-content.component';
81
import { IgxPivotGridColumnResizerComponent } from '../resizing/pivot-grid/pivot-resizer.component';
82
import { ISortingExpression, SortingDirection } from '../../data-operations/sorting-strategy';
83
import { PivotSortUtil } from './pivot-sort-util';
84
import { IFilteringStrategy } from '../../data-operations/filtering-strategy';
85
import { IgxPivotRowDimensionHeaderTemplateDirective, IgxPivotValueChipTemplateDirective } from './pivot-grid.directives';
86
import { IFilteringOperation } from '../../data-operations/filtering-condition';
87
import { IgxGridValidationService } from '../grid/grid-validation.service';
88
import { IgxPivotRowPipe, IgxPivotRowExpansionPipe, IgxPivotAutoTransform, IgxPivotColumnPipe, IgxPivotGridFilterPipe, IgxPivotGridSortingPipe, IgxPivotGridColumnSortingPipe, IgxPivotCellMergingPipe, IgxPivotGridHorizontalRowGrouping } from './pivot-grid.pipes';
89
import { IgxGridRowClassesPipe, IgxGridRowStylesPipe } from '../common/pipes';
90
import { IgxExcelStyleSearchComponent } from '../filtering/excel-style/excel-style-search.component';
91
import { IgxIconComponent } from '../../icon/icon.component';
92
import { IgxSnackbarComponent } from '../../snackbar/snackbar.component';
93
import { IgxCircularProgressBarComponent } from '../../progressbar/progressbar.component';
94
import { IgxToggleDirective, IgxOverlayOutletDirective } from '../../directives/toggle/toggle.directive';
95
import { IgxPivotRowComponent } from './pivot-row.component';
96
import { IgxTemplateOutletDirective } from '../../directives/template-outlet/template_outlet.directive';
97
import { IgxColumnMovingDropDirective } from '../moving/moving.drop.directive';
98
import { IgxGridDragSelectDirective } from '../selection/drag-select.directive';
99
import { IgxGridBodyDirective } from '../grid.common';
100
import { IgxColumnResizingService } from '../resizing/resizing.service';
101
import { DefaultDataCloneStrategy, IDataCloneStrategy } from '../../data-operations/data-clone-strategy';
102
import { IgxTextHighlightService } from '../../directives/text-highlight/text-highlight.service';
103
import { IgxPivotRowHeaderGroupComponent } from './pivot-row-header-group.component';
104
import { IgxPivotDateDimension } from './pivot-grid-dimensions';
105
import { IgxPivotRowDimensionMrlRowComponent } from './pivot-row-dimension-mrl-row.component';
106
import { IgxPivotGridRow } from  '../grid-public-row';
107

108
let NEXT_ID = 0;
3✔
109
const MINIMUM_COLUMN_WIDTH = 200;
3✔
110
const MINIMUM_COLUMN_WIDTH_SUPER_COMPACT = 104;
3✔
111

112
/* blazorAdditionalDependency: Column */
113
/* blazorAdditionalDependency: ColumnGroup */
114
/* blazorAdditionalDependency: ColumnLayout */
115
/* blazorAdditionalDependency: GridToolbar */
116
/* blazorAdditionalDependency: GridToolbarActions */
117
/* blazorAdditionalDependency: GridToolbarTitle */
118
/* blazorAdditionalDependency: GridToolbarAdvancedFiltering */
119
/* blazorAdditionalDependency: GridToolbarExporter */
120
/* blazorAdditionalDependency: GridToolbarHiding */
121
/* blazorAdditionalDependency: GridToolbarPinning */
122
/* blazorAdditionalDependency: ActionStrip */
123
/* blazorAdditionalDependency: GridActionsBaseDirective */
124
/* blazorAdditionalDependency: GridEditingActions */
125
/* blazorAdditionalDependency: GridPinningActions */
126
/* blazorAdditionalDependency: PivotDateDimension */
127
/* blazorIndirectRender */
128
/**
129
 * Pivot Grid provides a way to present and manipulate data in a pivot table view.
130
 *
131
 * @igxModule IgxPivotGridModule
132
 * @igxGroup Grids & Lists
133
 * @igxKeywords pivot, grid, table
134
 * @igxTheme igx-grid-theme
135
 * @remarks
136
 * The Ignite UI Pivot Grid is used for grouping and aggregating simple flat data into a pivot table.  Once data
137
 * has been bound and the dimensions and values configured it can be manipulated via sorting and filtering.
138
 * @example
139
 * ```html
140
 * <igx-pivot-grid [data]="data" [pivotConfiguration]="configuration">
141
 * </igx-pivot-grid>
142
 * ```
143
 */
144
@Component({
145
    changeDetection: ChangeDetectionStrategy.OnPush,
146
    preserveWhitespaces: false,
147
    selector: 'igx-pivot-grid',
148
    templateUrl: 'pivot-grid.component.html',
149
    providers: [
150
        IgxGridCRUDService,
151
        IgxGridValidationService,
152
        IgxGridSummaryService,
153
        IgxGridSelectionService,
154
        IgxColumnResizingService,
155
        GridBaseAPIService,
156
        { provide: IGX_GRID_SERVICE_BASE, useClass: GridBaseAPIService },
157
        { provide: IGX_GRID_BASE, useExisting: IgxPivotGridComponent },
158
        { provide: IgxFilteringService, useClass: IgxPivotFilteringService },
159
        IgxPivotGridNavigationService,
160
        IgxPivotColumnResizingService,
161
        IgxForOfSyncService,
162
        IgxForOfScrollSyncService
163
    ],
164
    imports: [
165
        NgClass,
166
        NgStyle,
167
        NgTemplateOutlet,
168
        IgxPivotHeaderRowComponent,
169
        IgxGridBodyDirective,
170
        IgxGridDragSelectDirective,
171
        IgxColumnMovingDropDirective,
172
        IgxGridForOfDirective,
173
        IgxTemplateOutletDirective,
174
        IgxPivotRowComponent,
175
        IgxToggleDirective,
176
        IgxCircularProgressBarComponent,
177
        IgxSnackbarComponent,
178
        IgxOverlayOutletDirective,
179
        IgxPivotGridColumnResizerComponent,
180
        IgxIconComponent,
181
        IgxPivotRowDimensionContentComponent,
182
        IgxGridExcelStyleFilteringComponent,
183
        IgxExcelStyleColumnOperationsTemplateDirective,
184
        IgxExcelStyleFilterOperationsTemplateDirective,
185
        IgxExcelStyleSearchComponent,
186
        IgxGridRowClassesPipe,
187
        IgxGridRowStylesPipe,
188
        IgxPivotRowPipe,
189
        IgxPivotRowExpansionPipe,
190
        IgxPivotAutoTransform,
191
        IgxPivotColumnPipe,
192
        IgxPivotGridFilterPipe,
193
        IgxPivotGridSortingPipe,
194
        IgxPivotGridColumnSortingPipe,
195
        IgxPivotCellMergingPipe,
196
        IgxPivotGridHorizontalRowGrouping,
197
        IgxPivotRowDimensionMrlRowComponent
198
    ],
199
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
200
})
201
export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnInit, AfterContentInit,
3✔
202
    GridType, AfterViewInit, OnChanges {
203

204
    /**
205
     * Emitted when the dimension collection is changed via the grid chip area.
206
     *
207
     * @remarks
208
     * Returns the new dimension collection and its type:
209
     * @example
210
     * ```html
211
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
212
     *              (dimensionsChange)="dimensionsChange($event)"></igx-grid>
213
     * ```
214
     */
215
    @Output()
216
    public dimensionsChange = new EventEmitter<IDimensionsChange>();
132✔
217

218
    /**
219
     * Emitted when any of the pivotConfiguration properties is changed via the grid chip area.
220
     *
221
     * @example
222
     * ```html
223
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
224
     *              (pivotConfigurationChanged)="configurationChanged($event)"></igx-grid>
225
     * ```
226
     */
227
    @Output()
228
    public pivotConfigurationChange = new EventEmitter<IPivotConfigurationChangedEventArgs>();
132✔
229

230

231
    /**
232
     * Emitted when the dimension is initialized.
233
     * @remarks
234
     * Emits the dimension that is about to be initialized.
235
     * @example
236
     * ```html
237
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
238
     *              (dimensionInit)="dimensionInit($event)"></igx-pivot-grid>
239
     * ```
240
     */
241
    @Output()
242
    public dimensionInit = new EventEmitter<IPivotDimension>();
132✔
243

244
    /**
245
     * Emitted when the value is initialized.
246
     * @remarks
247
     * Emits the value that is about to be initialized.
248
     * @example
249
     * ```html
250
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
251
     *              (valueInit)="valueInit($event)"></igx-pivot-grid>
252
     * ```
253
     */
254
    @Output()
255
    public valueInit = new EventEmitter<IPivotValue>();
132✔
256

257

258
    /**
259
     * Emitted when a dimension is sorted.
260
     *
261
     * @example
262
     * ```html
263
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
264
     *              (dimensionsSortingExpressionsChange)="dimensionsSortingExpressionsChange($event)"></igx-pivot-grid>
265
     * ```
266
     */
267
    @Output()
268
    public dimensionsSortingExpressionsChange = new EventEmitter<ISortingExpression[]>();
132✔
269

270
    /**
271
     * Emitted when the values collection is changed via the grid chip area.
272
     *
273
     * @remarks
274
     * Returns the new dimension
275
     * @example
276
     * ```html
277
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
278
     *              (valuesChange)="valuesChange($event)"></igx-grid>
279
     * ```
280
    */
281
    @Output()
282
    public valuesChange = new EventEmitter<IValuesChange>();
132✔
283

284

285
    /**
286
     * Gets the sorting expressions generated for the dimensions.
287
     *
288
     * @example
289
     * ```typescript
290
     * const expressions = this.grid.dimensionsSortingExpressions;
291
     * ```
292
     */
293
    public get dimensionsSortingExpressions() {
294
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
22✔
295
        const dimensionsSortingExpressions = PivotSortUtil.generateDimensionSortingExpressions(allEnabledDimensions);
22✔
296
        return dimensionsSortingExpressions;
22✔
297
    }
298

299
    /** @hidden @internal */
300
    @ViewChild(IgxPivotHeaderRowComponent, { static: true })
301
    public override theadRow: IgxPivotHeaderRowComponent;
302

303
    /**
304
    * @hidden @internal
305
    */
306
    @ContentChild(IgxPivotValueChipTemplateDirective, { read: IgxPivotValueChipTemplateDirective })
307
    protected valueChipTemplateDirective: IgxPivotValueChipTemplateDirective;
308

309
    /**
310
     * @hidden @internal
311
     */
312
    @ContentChild(IgxPivotRowDimensionHeaderTemplateDirective, { read: IgxPivotRowDimensionHeaderTemplateDirective })
313
    protected rowDimensionHeaderDirective: IgxPivotRowDimensionHeaderTemplateDirective;
314

315
    /**
316
     * Gets/Sets a custom template for the value chips.
317
     *
318
     * @example
319
     * ```html
320
     * <igx-pivot-grid [valueChipTemplate]="myTemplate"><igx-pivot-grid>
321
     * ```
322
     */
323
    @Input()
324
    public valueChipTemplate: TemplateRef<IgxPivotGridValueTemplateContext>;
325

326
    @Input()
327
    public rowDimensionHeaderTemplate: TemplateRef<IgxColumnTemplateContext>;
328

329
    /* mustSetInCodePlatforms: WebComponents;Blazor;React */
330
    /* @tsTwoWayProperty (true, "PivotConfigurationChange", "Detail.PivotConfiguration", false) */
331
    /**
332
     * Gets/Sets the pivot configuration with all related dimensions and values.
333
     *
334
     * @example
335
     * ```html
336
     * <igx-pivot-grid [pivotConfiguration]="config"></igx-pivot-grid>
337
     * ```
338
     */
339
    @Input()
340
    public set pivotConfiguration(value: IPivotConfiguration) {
341
        this._pivotConfiguration = value;
156✔
342
        this.emitInitEvents(this._pivotConfiguration);
156✔
343
        this.filteringExpressionsTree = PivotUtil.buildExpressionTree(value);
156✔
344
        if (!this._init) {
156✔
345
            this.setupColumns();
22✔
346
        }
347
        this.notifyChanges(true);
156✔
348
    }
349

350
    /* mustSetInCodePlatforms: WebComponents;Blazor */
351
    public get pivotConfiguration() {
352
        return this._pivotConfiguration || { rows: null, columns: null, values: null, filters: null };
928,777✔
353
    }
354

355
    /**
356
     * Gets/Sets whether to auto-generate the pivot configuration based on the provided data.
357
     *
358
     * @remarks
359
     * The default value is false. When set to true, it will override all dimensions and values in the pivotConfiguration.
360
     * @example
361
     * ```html
362
     * <igx-pivot-grid [data]="Data" [autoGenerateConfig]="true"></igx-pivot-grid>
363
     * ```
364
     */
365
    @Input({ transform: booleanAttribute })
366
    public autoGenerateConfig = false;
132✔
367

368
    @Input()
369
    /**
370
     * Gets/Sets the pivot ui settings for the pivot grid - chips and their
371
     * corresponding containers for row, filter, column dimensions and values
372
     * as well as headers for the row dimensions values.
373
     * @example
374
     * ```html
375
     * <igx-pivot-grid [pivotUI]="{ showRowHeaders: true }"></igx-pivot-grid>
376
     * ```
377
     */
378
    public set pivotUI(value: IPivotUISettings) {
379
        this._pivotUI = Object.assign(this._pivotUI, value || {});
11!
380
        this.pipeTrigger++;
11✔
381
        this.notifyChanges(true);
11✔
382
    }
383

384
    public get pivotUI() {
385
        return this._pivotUI;
134,540✔
386
    }
387

388
    /**
389
     * @hidden @internal
390
     */
391
    @HostBinding('attr.role')
392
    public role = 'grid';
132✔
393

394

395
    /**
396
     * Enables a super compact theme for the component.
397
     * @remarks
398
     * Overrides the grid size option if one is set.
399
     * @example
400
     * ```html
401
     * <igx-pivot-grid [superCompactMode]="true"></igx-pivot-grid>
402
     * ```
403
     */
404
    @HostBinding('class.igx-grid__pivot--super-compact')
405
    @Input()
406
    public get superCompactMode() {
407
        return this._superCompactMode;
120,558✔
408
    }
409

410
    public set superCompactMode(value) {
411
        this._superCompactMode = value;
3✔
412
    }
413

414
    /** @hidden @internal */
415
    public override get gridSize() {
416
        if (this.superCompactMode) {
114,031✔
417
            return Size.Small;
139✔
418
        }
419
        return super.gridSize;
113,892✔
420
    }
421

422

423
    /**
424
     * Gets/Sets the values clone strategy of the pivot grid when assigning them to different dimensions.
425
     *
426
     * @example
427
     * ```html
428
     *  <igx-pivot-grid #grid [data]="localData" [pivotValueCloneStrategy]="customCloneStrategy"></igx-pivot-grid>
429
     * ```
430
     * @hidden @internal
431
     */
432
    @Input()
433
    public get pivotValueCloneStrategy(): IDataCloneStrategy {
434
        return this._pivotValueCloneStrategy;
4,560✔
435
    }
436

437
    public set pivotValueCloneStrategy(strategy: IDataCloneStrategy) {
438
        if (strategy) {
×
439
            this._pivotValueCloneStrategy = strategy;
×
440
        }
441
    }
442

443
    /**
444
     * @hidden @internal
445
     */
446
    @ViewChild('record_template', { read: TemplateRef, static: true })
447
    public recordTemplate: TemplateRef<any>;
448

449
    /**
450
     * @hidden @internal
451
     */
452
    @ViewChild('headerTemplate', { read: TemplateRef, static: true })
453
    public headerTemplate: TemplateRef<any>;
454

455
    /**
456
     * @hidden @internal
457
     */
458
    @ViewChildren('rowDimensionContainer', { read: ElementRef })
459
    public rowDimensionContainer: QueryList<ElementRef<any>>;
460

461
    /**
462
     * @hidden @internal
463
     */
464
    @ViewChild(IgxPivotGridColumnResizerComponent)
465
    public override resizeLine: IgxPivotGridColumnResizerComponent;
466

467
    /**
468
     * @hidden @internal
469
     */
470
    @ViewChildren(IgxGridExcelStyleFilteringComponent, { read: IgxGridExcelStyleFilteringComponent })
471
    public override excelStyleFilteringComponents: QueryList<IgxGridExcelStyleFilteringComponent>;
472

473
    /**
474
     * @hidden @internal
475
     */
476
    @ViewChildren(IgxPivotRowDimensionContentComponent)
477
    protected rowDimensionContentCollection: QueryList<IgxPivotRowDimensionContentComponent>;
478

479
    /**
480
     * @hidden @internal
481
     */
482
    public override get minColumnWidth() {
483
        if (this.superCompactMode) {
5,629✔
484
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
1✔
485
        } else {
486
            return MINIMUM_COLUMN_WIDTH;
5,628✔
487
        }
488
    }
489

490
    /**
491
     * @hidden @internal
492
     */
493
    @ViewChildren('verticalRowDimScrollContainer', { read: IgxGridForOfDirective })
494
    public verticalRowDimScrollContainers: QueryList<IgxGridForOfDirective<any, any[]>>;
495

496
    /**
497
     * @hidden @internal
498
     */
499
    @ViewChildren(IgxPivotRowDimensionMrlRowComponent)
500
    public rowDimensionMrlRowsCollection: QueryList<IgxPivotRowDimensionMrlRowComponent>;
501

502
    /**
503
     * @hidden @internal
504
     */
505
    @Input()
506
    public override addRowEmptyTemplate: TemplateRef<void>;
507

508
    /**
509
     * @hidden @internal
510
     */
511
    @Input()
512
    public override autoGenerateExclude: string[] = [];
132✔
513

514
    /**
515
     * @hidden @internal
516
     */
517
    @Input()
518
    public override snackbarDisplayTime = 6000;
132✔
519

520
    /**
521
     * @hidden @internal
522
     */
523
    @Output()
524
    public override cellEdit = new EventEmitter<IGridEditEventArgs>();
132✔
525

526
    /**
527
     * @hidden @internal
528
     */
529
    @Output()
530
    public override cellEditDone = new EventEmitter<IGridEditDoneEventArgs>();
132✔
531

532
    /**
533
     * @hidden @internal
534
     */
535
    @Output()
536
    public override cellEditEnter = new EventEmitter<IGridEditEventArgs>();
132✔
537

538
    /**
539
     * @hidden @internal
540
     */
541
    @Output()
542
    public override cellEditExit = new EventEmitter<IGridEditDoneEventArgs>();
132✔
543

544
    /**
545
     * @hidden @internal
546
     */
547
    @Output()
548
    public override columnMovingStart = new EventEmitter<IColumnMovingStartEventArgs>();
132✔
549

550
    /**
551
     * @hidden @internal
552
     */
553
    @Output()
554
    public override columnMoving = new EventEmitter<IColumnMovingEventArgs>();
132✔
555

556
    /**
557
     * @hidden @internal
558
     */
559
    @Output()
560
    public override columnMovingEnd = new EventEmitter<IColumnMovingEndEventArgs>();
132✔
561

562
    /**
563
     * @hidden @internal
564
     */
565
    @Output()
566
    public override columnPin = new EventEmitter<IPinColumnCancellableEventArgs>();
132✔
567

568
    /**
569
     * @hidden @internal
570
     */
571
    @Output()
572
    public override columnPinned = new EventEmitter<IPinColumnEventArgs>();
132✔
573

574
    /**
575
     * @hidden @internal
576
     */
577
    @Output()
578
    public override rowAdd = new EventEmitter<IRowDataCancelableEventArgs>();
132✔
579

580
    /**
581
     * @hidden @internal
582
     */
583
    @Output()
584
    public override rowAdded = new EventEmitter<IRowDataEventArgs>();
132✔
585

586
    /**
587
     * @hidden @internal
588
     */
589
    @Output()
590
    public override rowDeleted = new EventEmitter<IRowDataEventArgs>();
132✔
591

592
    /**
593
     * @hidden @internal
594
     */
595
    @Output()
596
    public override rowDelete = new EventEmitter<IRowDataCancelableEventArgs>();
132✔
597

598
    /**
599
     * @hidden @internal
600
     */
601
    @Output()
602
    public override rowDragStart = new EventEmitter<IRowDragStartEventArgs>();
132✔
603

604
    /**
605
     * @hidden @internal
606
     */
607
    @Output()
608
    public override rowDragEnd = new EventEmitter<IRowDragEndEventArgs>();
132✔
609

610
    /**
611
     * @hidden @internal
612
     */
613
    @Output()
614
    public override rowEditEnter = new EventEmitter<IGridEditEventArgs>();
132✔
615

616
    /**
617
     * @hidden @internal
618
     */
619
    @Output()
620
    public override rowEdit = new EventEmitter<IGridEditEventArgs>();
132✔
621

622
    /**
623
     * @hidden @internal
624
     */
625
    @Output()
626
    public override rowEditDone = new EventEmitter<IGridEditDoneEventArgs>();
132✔
627

628
    /**
629
     * @hidden @internal
630
     */
631
    @Output()
632
    public override rowEditExit = new EventEmitter<IGridEditDoneEventArgs>();
132✔
633

634
    /**
635
     * @hidden @internal
636
     */
637
    @Output()
638
    public override rowPinning = new EventEmitter<IPinRowEventArgs>();
132✔
639

640
    /**
641
     * @hidden @internal
642
     */
643
    @Output()
644
    public override rowPinned = new EventEmitter<IPinRowEventArgs>();
132✔
645

646
    /** @hidden @internal */
647
    public columnGroupStates = new Map<string, boolean>();
132✔
648
    /** @hidden @internal */
649
    public dimensionDataColumns: any[];
650
    /** @hidden @internal */
651
    public get pivotKeys() {
652
        return this.pivotConfiguration.pivotKeys || DEFAULT_PIVOT_KEYS;
162,982✔
653
    }
654
    /** @hidden @internal */
655
    public override get type(): GridType["type"] {
656
        return 'pivot';
5,276✔
657
    }
658

659
    /**
660
     * @hidden @internal
661
     */
662
    public override dragRowID = null;
132✔
663

664
    /**
665
    * @hidden @internal
666
    */
667
    public override get rootSummariesEnabled(): boolean {
668
        return false;
5,422✔
669
    }
670

671
    /**
672
     * @hidden @internal
673
     */
674
    public rowDimensionResizing = true;
132✔
675

676
    private _emptyRowDimension: IPivotDimension = { memberName: '', enabled: true, level: 0 };
132✔
677
    /**
678
     * @hidden @internal
679
     */
680
    public get emptyRowDimension(): IPivotDimension {
681
        return this._emptyRowDimension;
2,895✔
682
    }
683

684
    protected _pivotValueCloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy();
132✔
685
    protected override _defaultExpandState = false;
132✔
686
    protected override _filterStrategy: IFilteringStrategy = new DimensionValuesFilteringStrategy();
132✔
687
    protected regroupTrigger = 0;
132✔
688
    private _data;
689
    private _pivotConfiguration: IPivotConfiguration = { rows: null, columns: null, values: null, filters: null };
132✔
690
    private p_id = `igx-pivot-grid-${NEXT_ID++}`;
132✔
691
    private _superCompactMode = false;
132✔
692
    private _pivotUI: IPivotUISettings = {
132✔
693
        showConfiguration: true,
694
        showRowHeaders: false,
695
        rowLayout: PivotRowLayoutType.Vertical,
696
        horizontalSummariesPosition: PivotSummaryPosition.Bottom
697
    };
698
    private _sortableColumns = true;
132✔
699
    private _visibleRowDimensions: IPivotDimension[] = [];
132✔
700
    private _shouldUpdateSizes = false;
132✔
701

702
    /**
703
    * Gets/Sets the default expand state for all rows.
704
    */
705
    @Input({ transform: booleanAttribute })
706
    public get defaultExpandState() {
707
        return this._defaultExpandState;
2,152✔
708
    }
709

710
    public set defaultExpandState(val: boolean) {
711
        this._defaultExpandState = val;
122✔
712
    }
713

714
    /**
715
     * @hidden @internal
716
     */
717
    @Input()
718
    public override get pagingMode() {
719
        return;
×
720
    }
721

722
    public override set pagingMode(_val: GridPagingMode) {
723
    }
724

725
    /**
726
     * @hidden @internal
727
     */
728
    @WatchChanges()
729
    @Input({ transform: booleanAttribute })
730
    public override get hideRowSelectors() {
731
        return;
×
732
    }
733

734
    public override set hideRowSelectors(_value: boolean) {
735
    }
736

737
    /**
738
     * @hidden @internal
739
     */
740
    public override autoGenerate = true;
132✔
741

742
    /**
743
     * @hidden @internal
744
     */
745
    public override get actionStrip() {
746
        return undefined as any;
×
747
    }
748

749
    /**
750
     * @hidden @internal
751
     * @deprecated in version 18.2.0. This property is no longer supported.
752
     */
753
    public override get shouldGenerate(): boolean {
754
        return false;
×
755
    }
756

757
    public override set shouldGenerate(value: boolean) {
758
    }
759

760
    /**
761
     * @hidden @internal
762
     */
763
    public override moving = false;
132✔
764

765
    /**
766
     * @hidden @internal
767
     */
768
    public override toolbarExporting = new EventEmitter<IGridToolbarExportEventArgs>();
132✔
769

770
    /**
771
     * @hidden @internal
772
     */
773
    @Input({ transform: booleanAttribute })
774
    public override get rowDraggable(): boolean {
775
        return;
×
776
    }
777

778

779
    public override set rowDraggable(_val: boolean) {
780
    }
781

782
    /**
783
     * @hidden @internal
784
     */
785
    @Input({ transform: booleanAttribute })
786
    public override get allowAdvancedFiltering() {
787
        return false;
×
788
    }
789

790
    public override set allowAdvancedFiltering(_value) {
791
    }
792

793
    /**
794
     * @hidden @internal
795
     */
796
    @Input()
797
    public override get filterMode() {
798
        return FilterMode.quickFilter;
×
799
    }
800

801
    public override set filterMode(_value: FilterMode) {
802
    }
803

804
    /**
805
     * @hidden @internal
806
     */
807
    @Input({ transform: booleanAttribute })
808
    public override get allowFiltering() {
809
        return false;
36,020✔
810
    }
811

812
    public override set allowFiltering(_value) {
813
    }
814

815
    /**
816
     * @hidden @internal
817
     */
818
    @Input()
819
    public override get page(): number {
820
        return 0;
×
821
    }
822

823
    public override set page(_val: number) {
824
    }
825

826
    /**
827
     * @hidden @internal
828
     */
829
    @Input()
830
    public override get perPage(): number {
831
        return;
×
832
    }
833

834
    public override set perPage(_val: number) {
835
    }
836

837
    /**
838
     * @hidden @internal
839
     */
840
    public override get pinnedColumns(): IgxColumnComponent[] {
841
        return [];
147,263✔
842
    }
843

844
    /**
845
    * @hidden @internal
846
    */
847
    public override get unpinnedColumns(): IgxColumnComponent[] {
848
        return super.unpinnedColumns;
25,583✔
849
    }
850

851
    /**
852
    * @hidden @internal
853
    */
854
    public override get unpinnedDataView(): any[] {
855
        return super.unpinnedDataView;
×
856
    }
857

858
    /**
859
    * @hidden @internal
860
    */
861
    public override get unpinnedWidth() {
862
        return super.unpinnedWidth;
23,080✔
863
    }
864

865
    /**
866
     * @hidden @internal
867
     */
868
    public override get pinnedWidth() {
869
        return super.pinnedWidth;
5,975✔
870
    }
871

872
    /**
873
     * @hidden @internal
874
     */
875
    @Input()
876
    public override set summaryRowHeight(_value: number) {
877
    }
878

879
    public override get summaryRowHeight(): number {
880
        return 0;
602✔
881
    }
882

883
    /**
884
     * @hidden @internal
885
     */
886
    public override get transactions(): TransactionService<Transaction, State> {
887
        return this._transactions;
527,672✔
888
    }
889

890

891

892
    /**
893
     * @hidden @internal
894
     */
895
    public override get dragIndicatorIconTemplate(): TemplateRef<any> {
896
        return;
×
897
    }
898

899
    public override set dragIndicatorIconTemplate(_val: TemplateRef<any>) {
900
    }
901

902
    /**
903
     * @hidden @internal
904
     */
905
    @WatchChanges()
906
    @Input({ transform: booleanAttribute })
907
    public override get rowEditable(): boolean {
908
        return;
224,265✔
909
    }
910

911
    public override set rowEditable(_val: boolean) {
912
    }
913

914
    /**
915
     * @hidden @internal
916
     */
917
    @Input()
918
    public override get pinning() {
919
        return {};
181,362✔
920
    }
921
    public override set pinning(_value) {
922
    }
923

924
    /**
925
     * @hidden @internal
926
     */
927
    @Input()
928
    public override get summaryPosition() {
929
        return;
×
930
    }
931

932
    public override set summaryPosition(_value: GridSummaryPosition) {
933
    }
934

935
    /**
936
     * @hidden @interal
937
     */
938
    @Input()
939
    public override get summaryCalculationMode() {
940
        return;
×
941
    }
942

943
    public override set summaryCalculationMode(_value: GridSummaryCalculationMode) {
944
    }
945

946
    /**
947
     * @hidden @interal
948
     */
949
    @Input({ transform: booleanAttribute })
950
    public override get showSummaryOnCollapse() {
951
        return;
×
952
    }
953

954
    public override set showSummaryOnCollapse(_value: boolean) {
955
    }
956

957
    /**
958
     * @hidden @internal
959
     */
960
    public override get hiddenColumnsCount() {
961
        return null;
×
962
    }
963

964
    /**
965
     * @hidden @internal
966
     */
967
    public override get pinnedColumnsCount() {
968
        return null;
×
969
    }
970

971
    /**
972
     * @hidden @internal
973
     */
974
    @Input({ transform: booleanAttribute })
975
    public override get batchEditing(): boolean {
976
        return;
×
977
    }
978

979
    public override set batchEditing(_val: boolean) {
980
    }
981

982
    /* csSuppress */
983
    public override get selectedRows(): any[] {
984
        if (this.selectionService.getSelectedRows().length === 0) {
19✔
985
            return [];
4✔
986
        }
987
        const selectedRowIds = [];
15✔
988
        this.dataView.forEach(record => {
15✔
989
            const prev = [];
182✔
990
            for (const dim of this.rowDimensions) {
182✔
991
                let currDim = dim;
345✔
992
                let shouldBreak = false;
345✔
993
                do {
345✔
994
                    const key = PivotUtil.getRecordKey(record, currDim);
651✔
995
                    if (this.selectionService.isPivotRowSelected(key) && !selectedRowIds.find(x => x === record)) {
651✔
996
                        selectedRowIds.push(record);
29✔
997
                        shouldBreak = true;
29✔
998
                        break;
29✔
999
                    }
1000
                    currDim = currDim.childLevel;
622✔
1001
                } while (currDim);
1002
                prev.push(dim);
345✔
1003
                if (shouldBreak) {
345✔
1004
                    break;
29✔
1005
                }
1006
            }
1007

1008
        });
1009

1010
        return selectedRowIds;
15✔
1011
    }
1012

1013
    constructor(
1014
        validationService: IgxGridValidationService,
1015
        selectionService: IgxGridSelectionService,
1016
        colResizingService: IgxPivotColumnResizingService,
1017
        gridAPI: GridBaseAPIService<IgxGridBaseDirective & GridType>,
1018
        transactionFactory: IgxFlatTransactionFactory,
1019
        elementRef: ElementRef<HTMLElement>,
1020
        zone: NgZone,
1021
        @Inject(DOCUMENT) document,
1022
        cdr: ChangeDetectorRef,
1023
        differs: IterableDiffers,
1024
        viewRef: ViewContainerRef,
1025
        injector: Injector,
1026
        envInjector: EnvironmentInjector,
1027
        public override navigation: IgxPivotGridNavigationService,
132✔
1028
        filteringService: IgxFilteringService,
1029
        textHighlightService: IgxTextHighlightService,
1030
        @Inject(IgxOverlayService) overlayService: IgxOverlayService,
1031
        summaryService: IgxGridSummaryService,
1032
        @Inject(LOCALE_ID) localeId: string,
1033
        platform: PlatformUtil,
1034
        @Optional() @Inject(IgxGridTransaction) _diTransactions?: TransactionService<Transaction, State>
1035
    ) {
1036
        super(
132✔
1037
            validationService,
1038
            selectionService,
1039
            colResizingService,
1040
            gridAPI,
1041
            transactionFactory,
1042
            elementRef,
1043
            zone,
1044
            document,
1045
            cdr,
1046
            differs,
1047
            viewRef,
1048
            injector,
1049
            envInjector,
1050
            navigation,
1051
            filteringService,
1052
            textHighlightService,
1053
            overlayService,
1054
            summaryService,
1055
            localeId,
1056
            platform,
1057
            _diTransactions);
1058
    }
1059

1060
    /**
1061
     * @hidden
1062
     */
1063
    public override ngOnInit() {
1064
        // pivot grid always generates columns automatically.
1065
        this.autoGenerate = true;
132✔
1066
        super.ngOnInit();
132✔
1067
    }
1068

1069
    /**
1070
     * @hidden
1071
     */
1072
    public override ngAfterContentInit() {
1073
        // ignore any user defined columns and auto-generate based on pivot config.
1074
        this.updateColumns([]);
132✔
1075
        Promise.resolve().then(() => {
132✔
1076
            if (this.autoGenerateConfig) {
132!
1077
                this.generateConfig();
×
1078
            }
1079
            this.setupColumns();
132✔
1080
        });
1081
        if (this.valueChipTemplateDirective) {
132!
1082
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
×
1083
        }
1084
        if (this.rowDimensionHeaderDirective) {
132!
1085
            this.rowDimensionHeaderTemplate = this.rowDimensionHeaderDirective.template;
×
1086
        }
1087
    }
1088

1089
    /**
1090
     * @hidden @internal
1091
     */
1092
    public override ngAfterViewInit() {
1093
        Promise.resolve().then(() => {
132✔
1094
            super.ngAfterViewInit();
132✔
1095
        });
1096
    }
1097

1098
    /**
1099
     * @hidden @internal
1100
     */
1101
    public ngOnChanges(changes: SimpleChanges) {
1102
        if (changes.superCompactMode && !changes.superCompactMode.isFirstChange()) {
180!
1103
            this._shouldUpdateSizes = true;
×
1104
            resizeObservable(this.verticalScrollContainer.displayContainer).pipe(take(1), takeUntil(this.destroy$)).subscribe(() => this.resizeNotify.next());
×
1105
        }
1106
    }
1107

1108
    /**
1109
     * Notifies for dimension change.
1110
     */
1111
    public notifyDimensionChange(regenerateColumns = false) {
×
1112
        if (regenerateColumns) {
19✔
1113
            this.setupColumns();
19✔
1114
        }
1115
        this.pipeTrigger++;
19✔
1116
        this.cdr.detectChanges();
19✔
1117
    }
1118

1119
    /**
1120
     * Gets the full list of dimensions.
1121
     *
1122
     * @example
1123
     * ```typescript
1124
     * const dimensions = this.grid.allDimensions;
1125
     * ```
1126
     */
1127
    public get allDimensions() {
1128
        const config = this._pivotConfiguration;
1,667✔
1129
        if (!config) return [];
1,667✔
1130
        return (config.rows || []).concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
4,126!
1131
    }
1132

1133
    protected get allVisibleDimensions() {
1134
        const config = this._pivotConfiguration;
280✔
1135
        if (!config) return [];
280✔
1136
        const uniqueVisibleRowDims = this.visibleRowDimensions.filter(dim => !config.rows.find(configRow => configRow.memberName === dim.memberName));
327✔
1137
        const rows = (config.rows || []).concat(...uniqueVisibleRowDims);
276!
1138
        return rows.concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
779!
1139
    }
1140

1141
    protected override get shouldResize(): boolean {
1142
        if (!this.dataRowList.first?.cells || this.dataRowList.first.cells.length === 0) {
131!
1143
            return false;
×
1144
        }
1145
        const isSizePropChanged = super.shouldResize;
131✔
1146
        if (isSizePropChanged || this._shouldUpdateSizes) {
131✔
1147
            this._shouldUpdateSizes = false;
59✔
1148
            return true;
59✔
1149
        }
1150
        return false;
72✔
1151
    }
1152

1153
    protected get emptyBottomSize() {
1154
        return this.totalHeight - (<any>this.verticalScroll).scrollComponent.size;
4,793✔
1155
    }
1156

1157
    /** @hidden @internal */
1158
    public createFilterESF(dropdown: any, column: ColumnType, options: OverlaySettings, shouldReatach: boolean) {
1159
        options.outlet = this.outlet;
5✔
1160
        if (dropdown) {
5✔
1161
            dropdown.initialize(column, this.overlayService);
5✔
1162
            if (shouldReatach) {
5✔
1163
                const id = this.overlayService.attach(dropdown.element, options);
3✔
1164
                dropdown.overlayComponentId = id;
3✔
1165
                return { id, ref: undefined };
3✔
1166
            }
1167
            return { id: dropdown.overlayComponentId, ref: undefined };
2✔
1168
        }
1169
    }
1170

1171
    /** @hidden */
1172
    public override featureColumnsWidth() {
1173
        return this.pivotRowWidths || 0;
8,054✔
1174
    }
1175

1176
    /* blazorSuppress */
1177
    /**
1178
     * Gets/Sets the value of the `id` attribute.
1179
     *
1180
     * @remarks
1181
     * If not provided it will be automatically generated.
1182
     * @example
1183
     * ```html
1184
     * <igx-pivot-grid [id]="'igx-pivot-1'" [data]="Data"></igx-pivot-grid>
1185
     * ```
1186
     */
1187
    @HostBinding('attr.id')
1188
    @Input()
1189
    public get id(): string {
1190
        return this.p_id;
90,826✔
1191
    }
1192
    /* blazorSuppress */
1193
    public set id(value: string) {
1194
        this.p_id = value;
×
1195
    }
1196

1197
    /* treatAsRef */
1198
    /* blazorAlternateType: object */
1199
    /**
1200
     * Gets/Sets the array of data that populates the component.
1201
     * ```html
1202
     * <igx-pivot-grid [data]="Data"></igx-pivot-grid>
1203
     * ```
1204
     */
1205
    @Input()
1206
    public set data(value: any[] | null) {
1207
        this._data = value || [];
141!
1208
        if (!this._init) {
141✔
1209
            if (this.autoGenerateConfig) {
8✔
1210
                this.generateConfig();
1✔
1211
            }
1212
            this.setupColumns();
8✔
1213
            this.reflow();
8✔
1214
        }
1215
        this.cdr.markForCheck();
141✔
1216
        if (this.height === null || this.height.indexOf('%') !== -1) {
141✔
1217
            // If the height will change based on how much data there is, recalculate sizes in igxForOf.
1218
            this.notifyChanges(true);
54✔
1219
        }
1220
    }
1221

1222
    /* treatAsRef */
1223
    /* blazorAlternateType: object */
1224
    /**
1225
     * Returns an array of data set to the component.
1226
     * ```typescript
1227
     * let data = this.grid.data;
1228
     * ```
1229
     */
1230
    public get data(): any[] | null {
1231
        return this._data;
70,676✔
1232
    }
1233

1234
    /**
1235
     * @hidden
1236
     */
1237
    public getContext(rowData, rowIndex): any {
1238
        return {
10,879✔
1239
            $implicit: rowData,
1240
            templateID: {
1241
                type: 'dataRow',
1242
                id: null
1243
            },
1244
            index: this.getDataViewIndex(rowIndex, false)
1245
        };
1246
    }
1247

1248
    /**
1249
     * @hidden @internal
1250
     */
1251
    public get pivotRowWidths() {
1252
        return this.visibleRowDimensions.length ? this.visibleRowDimensions.reduce((accumulator, dim) => accumulator + this.rowDimensionWidthToPixels(dim), 0) :
20,182✔
1253
            this.rowDimensionWidthToPixels(this.emptyRowDimension);
1254
    }
1255

1256
    /**
1257
     * @hidden @internal
1258
     */
1259
    public rowDimensionWidth(dim): string {
1260
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
43,221✔
1261
        if (isAuto) {
43,221✔
1262
            return dim.autoWidth ? dim.autoWidth + 'px' : 'fit-content';
121!
1263
        } else {
1264
            return this.rowDimensionWidthToPixels(dim) + 'px';
43,100✔
1265
        }
1266
    }
1267

1268
    /**
1269
     * @hidden @internal
1270
     */
1271
    public rowDimensionWidthToPixels(dim: IPivotDimension): number {
1272
        if (!dim?.width) {
91,417✔
1273
            return MINIMUM_COLUMN_WIDTH;
88,242✔
1274
        }
1275
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
3,175✔
1276
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
3,175✔
1277
        if (isPercent) {
3,175✔
1278
            return Math.round(parseFloat(dim.width) / 100 * this.calcWidth);
695✔
1279
        } else if (isAuto) {
2,480✔
1280
            return dim.autoWidth;
108✔
1281
        } else {
1282
            return parseInt(dim.width, 10);
2,372✔
1283
        }
1284
    }
1285

1286
    /**
1287
     * @hidden @internal
1288
     */
1289
    public reverseDimensionWidthToPercent(width: number): number {
1290
        return (width * 100 / this.calcWidth);
1✔
1291
    }
1292

1293
    /** @hidden @internal */
1294
    public get pivotContentCalcWidth() {
1295
        if (!this.platform.isBrowser) {
2,152!
1296
            return undefined;
×
1297
        }
1298
        if (!this.visibleRowDimensions.length) {
2,152✔
1299
            return Math.max(0, this.calcWidth - this.pivotRowWidths);
221✔
1300
        }
1301

1302
        const totalDimWidth = this.visibleRowDimensions.length > 0 ?
1,931!
1303
            this.visibleRowDimensions.map((dim) => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur) :
3,023✔
1304
            0;
1305
        return this.calcWidth - totalDimWidth;
1,931✔
1306
    }
1307

1308
    /** @hidden @internal */
1309
    public get pivotPinnedWidth() {
1310
        return !this._init ? (this.isPinningToStart ? this.pinnedWidth : this.headerFeaturesWidth) : 0;
10,760!
1311
    }
1312

1313
    /** @hidden @internal */
1314
    public get pivotUnpinnedWidth() {
1315
        return this.unpinnedWidth || 0;
2,152!
1316
    }
1317

1318
    /** @hidden @internal */
1319
    public get rowDimensions() {
1320
        return this.pivotConfiguration.rows?.filter(x => x.enabled) || [];
112,233✔
1321
    }
1322

1323
    /** @hidden @internal */
1324
    public set visibleRowDimensions(value: IPivotDimension[]) {
1325
        this._visibleRowDimensions = value;
389✔
1326
    }
1327

1328
    public get visibleRowDimensions() {
1329
        return this._visibleRowDimensions || this.rowDimensions;
38,744!
1330
    }
1331

1332
    /** @hidden @internal */
1333
    public get columnDimensions() {
1334
        return this.pivotConfiguration.columns?.filter(x => x.enabled) || [];
305,236✔
1335
    }
1336

1337
    /** @hidden @internal */
1338
    public get filterDimensions() {
1339
        return this.pivotConfiguration.filters?.filter(x => x.enabled) || [];
6,214✔
1340
    }
1341

1342
    /** @hidden @internal */
1343
    public get values() {
1344
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
675,048✔
1345
    }
1346

1347
    public toggleColumn(col: IgxColumnComponent) {
1348
        const state = this.columnGroupStates.get(col.field);
4✔
1349
        const newState = !state;
4✔
1350
        this.columnGroupStates.set(col.field, newState);
4✔
1351
        this.toggleRowGroup(col, newState);
4✔
1352
        this.reflow();
4✔
1353
    }
1354

1355
    /**
1356
     * @hidden @internal
1357
     */
1358
    public override isRecordPinnedByIndex(_rowIndex: number) {
1359
        return null;
×
1360
    }
1361

1362
    /**
1363
     * @hidden @internal
1364
     */
1365
    public override toggleColumnVisibility(_args: IColumnVisibilityChangedEventArgs) {
1366
        return;
×
1367
    }
1368

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

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

1381
    /**
1382
     * @hidden @internal
1383
     */
1384
    public override expandRow(_rowID: any) {
1385
    }
1386

1387
    /**
1388
     * @hidden @internal
1389
     */
1390
    public override collapseRow(_rowID: any) {
1391
    }
1392

1393
    /**
1394
     * @hidden @internal
1395
     */
1396
    public override get pinnedRows(): IgxGridRowComponent[] {
1397
        return;
2✔
1398
    }
1399

1400
    /**
1401
     * @hidden @internal
1402
     */
1403
    @Input()
1404
    public override get totalRecords(): number {
1405
        return;
×
1406
    }
1407

1408
    public override set totalRecords(_total: number) {
1409
    }
1410

1411
    /**
1412
     * @hidden @internal
1413
     */
1414
    public override moveColumn(_column: IgxColumnComponent, _target: IgxColumnComponent, _pos: DropPosition = DropPosition.AfterDropTarget) {
×
1415
    }
1416

1417
    /**
1418
     * @hidden @internal
1419
     */
1420
    public override addRow(_data: any): void {
1421
    }
1422

1423
    /**
1424
     * @hidden @internal
1425
     */
1426
    public override deleteRow(_rowSelector: any): any {
1427
    }
1428

1429
    /**
1430
     * @hidden @internal
1431
     */
1432
    public override updateCell(_value: any, _rowSelector: any, _column: string): void {
1433
    }
1434

1435
    /**
1436
     * @hidden @internal
1437
     */
1438
    public override updateRow(_value: any, _rowSelector: any): void {
1439
    }
1440

1441
    /**
1442
     * @hidden @internal
1443
     */
1444
    public override enableSummaries(..._rest) {
1445
    }
1446

1447
    /**
1448
     * @hidden @internal
1449
     */
1450
    public override disableSummaries(..._rest) {
1451
    }
1452

1453
    /**
1454
     * @hidden @internal
1455
     */
1456
    public override pinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
1457
        return;
×
1458
    }
1459

1460
    /**
1461
     * @hidden @internal
1462
     */
1463
    public override unpinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
1464
        return;
×
1465
    }
1466

1467
    /**
1468
     * @hidden @internal
1469
     */
1470
    public override pinRow(_rowID: any, _index?: number, _row?: RowType): boolean {
1471
        return;
×
1472
    }
1473

1474
    /**
1475
     * @hidden @internal
1476
     */
1477
    public override unpinRow(_rowID: any, _row?: RowType): boolean {
1478
        return;
×
1479
    }
1480

1481
    /**
1482
     * @hidden @internal
1483
     */
1484
    public override get pinnedRowHeight() {
1485
        return;
2,754✔
1486
    }
1487

1488
    /**
1489
     * @hidden @internal
1490
     */
1491
    public override get hasEditableColumns(): boolean {
1492
        return;
×
1493
    }
1494

1495
    /**
1496
     * @hidden @internal
1497
     */
1498
    public override get hasSummarizedColumns(): boolean {
1499
        return;
5✔
1500
    }
1501

1502
    /**
1503
     * @hidden @internal
1504
     */
1505
    public override get hasMovableColumns(): boolean {
1506
        return;
38,268✔
1507
    }
1508

1509
    /**
1510
     * @hidden @internal
1511
     */
1512
    public override get pinnedDataView(): any[] {
1513
        return [];
10,879✔
1514
    }
1515

1516
    /**
1517
     * @hidden @internal
1518
     */
1519
    public override openAdvancedFilteringDialog(_overlaySettings?: OverlaySettings) {
1520
    }
1521

1522
    /**
1523
     * @hidden @internal
1524
     */
1525
    public override closeAdvancedFilteringDialog(_applyChanges: boolean) {
1526
    }
1527

1528
    /**
1529
     * @hidden @internal
1530
     */
1531
    public override endEdit(_commit = true, _event?: Event): boolean {
×
1532
        return;
×
1533
    }
1534

1535
    /**
1536
     * @hidden @internal
1537
     */
1538
    public override beginAddRowById(_rowID: any, _asChild?: boolean): void {
1539
    }
1540

1541
    /**
1542
     * @hidden @internal
1543
     */
1544
    public override beginAddRowByIndex(_index: number): void {
1545
    }
1546

1547
    /**
1548
     * @hidden @internal
1549
     */
1550
    public override clearSearch() { }
1551

1552
    /**
1553
    * @hidden @internal
1554
    */
1555
    public override refreshSearch(_updateActiveInfo?: boolean, _endEdit = true): number {
95✔
1556
        return 0;
484✔
1557
    }
1558

1559
    /**
1560
    * @hidden @internal
1561
    */
1562
    public override findNext(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
1563
        return 0;
×
1564
    }
1565

1566
    /**
1567
    * @hidden @internal
1568
    */
1569
    public override findPrev(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
1570
        return 0;
×
1571
    }
1572

1573
    /**
1574
    * @hidden @internal
1575
    */
1576
    public override getNextCell(currRowIndex: number, curVisibleColIndex: number,
1577
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
×
1578
        return super.getNextCell(currRowIndex, curVisibleColIndex, callback);
×
1579
    }
1580

1581
    /**
1582
    * @hidden @internal
1583
    */
1584
    public override getPreviousCell(currRowIndex: number, curVisibleColIndex: number,
1585
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
×
1586
        return super.getPreviousCell(currRowIndex, curVisibleColIndex, callback);
×
1587
    }
1588

1589
    /**
1590
    * @hidden @internal
1591
    */
1592
    public override getPinnedWidth(takeHidden = false) {
589✔
1593
        return super.getPinnedWidth(takeHidden);
2,422✔
1594
    }
1595

1596
    /**
1597
     * @hidden @internal
1598
     */
1599
    public override get totalHeight() {
1600
        return this.calcHeight;
9,753✔
1601
    }
1602

1603
    public getColumnGroupExpandState(col: IgxColumnComponent) {
1604
        const state = this.columnGroupStates.get(col.field);
177✔
1605
        // columns are expanded by default?
1606
        return state !== undefined && state !== null ? state : false;
177✔
1607
    }
1608

1609
    public toggleRowGroup(col: IgxColumnComponent, newState: boolean) {
1610
        if (!col) return;
5!
1611
        if (this.hasMultipleValues) {
5✔
1612
            const parentCols = col.parent ? col.parent.children.toArray() : this._autoGeneratedCols.filter(x => x.level === 0);
88!
1613
            const siblingCol = parentCols.filter(x => x.header === col.header && x !== col)[0];
8✔
1614
            const currIndex = parentCols.indexOf(col);
4✔
1615
            const siblingIndex = parentCols.indexOf(siblingCol);
4✔
1616
            if (currIndex < siblingIndex) {
4✔
1617
                // clicked on the full hierarchy header
1618
                this.resolveToggle(col, newState);
3✔
1619
                siblingCol.headerTemplate = this.headerTemplate;
3✔
1620
            } else {
1621
                // clicked on summary parent column that contains just the measures
1622
                col.headerTemplate = undefined;
1✔
1623
                this.resolveToggle(siblingCol, newState);
1✔
1624
            }
1625
        } else {
1626
            const parentCols = col.parent ? col.parent.children : this._autoGeneratedCols.filter(x => x.level === 0);
5!
1627
            const fieldColumn = parentCols.filter(x => x.header === col.header && !x.columnGroup)[0];
2✔
1628
            const groupColumn = parentCols.filter(x => x.header === col.header && x.columnGroup)[0];
2✔
1629
            this.resolveToggle(groupColumn, newState);
1✔
1630
            if (newState) {
1!
1631
                fieldColumn.headerTemplate = this.headerTemplate;
1✔
1632
            } else {
1633
                fieldColumn.headerTemplate = undefined;
×
1634
            }
1635
        }
1636
    }
1637

1638
    /**
1639
    * @hidden @internal
1640
    */
1641
    public override setupColumns() {
1642
        super.setupColumns();
247✔
1643
    }
1644

1645
    /**
1646
    * @hidden @internal
1647
    */
1648
    public override dataRebinding(event: IForOfDataChangingEventArgs) {
1649
        if (this.hasHorizontalLayout) {
358✔
1650
            this.dimensionDataColumns = this.generateDimensionColumns();
30✔
1651
        }
1652

1653
        super.dataRebinding(event);
358✔
1654
    }
1655

1656
    /**
1657
     * Auto-sizes row dimension cells.
1658
     *
1659
     * @remarks
1660
     * Only sizes based on the dimension cells in view.
1661
     * @example
1662
     * ```typescript
1663
     * this.grid.autoSizeRowDimension(dimension);
1664
     * ```
1665
     * @param dimension The row dimension to size.
1666
     */
1667
    public autoSizeRowDimension(dimension: IPivotDimension) {
1668
        if (this.getDimensionType(dimension) === PivotDimensionType.Row) {
2✔
1669
            const relatedDims: string[] = PivotUtil.flatten([dimension]).map((x: IPivotDimension) => x.memberName);
4✔
1670
            const contentCollection =  this.getContentCollection(dimension);
2✔
1671
            const content = contentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
19✔
1672
            const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
10✔
1673
            if (this.pivotUI.showRowHeaders) {
2!
1674
                const dimensionHeader = this.theadRow.rowDimensionHeaders.find(x => x.column.field === dimension.memberName);
×
1675
                headers.push(dimensionHeader);
×
1676
            }
1677
            const autoWidth = this.getLargesContentWidth(headers);
2✔
1678
            if (dimension.width === "auto") {
2!
1679
                dimension.autoWidth = parseFloat(autoWidth);
×
1680
            } else {
1681
                dimension.width = autoWidth;
2✔
1682
            }
1683
            this.pipeTrigger++;
2✔
1684
            this.cdr.detectChanges();
2✔
1685
        }
1686
    }
1687

1688
    /**
1689
     * Inserts dimension in target collection by type at specified index or at the collection's end.
1690
     *
1691
     * @example
1692
     * ```typescript
1693
     * this.grid.insertDimensionAt(dimension, PivotDimensionType.Row, 1);
1694
     * ```
1695
     * @param dimension The dimension that will be added.
1696
     * @param targetCollectionType The target collection type to add to. Can be Row, Column or Filter.
1697
     * @param index The index in the collection at which to add.
1698
     * This parameter is optional. If not set it will add it to the end of the collection.
1699
     */
1700
    public insertDimensionAt(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1701
        const targetCollection = this.getDimensionsByType(targetCollectionType);
12✔
1702
        if (index !== undefined) {
12✔
1703
            targetCollection.splice(index, 0, dimension);
11✔
1704
        } else {
1705
            targetCollection.push(dimension);
1✔
1706
        }
1707
        if (targetCollectionType === PivotDimensionType.Column) {
12✔
1708
            this.setupColumns();
4✔
1709
        }
1710
        this.pipeTrigger++;
12✔
1711
        this.dimensionsChange.emit({ dimensions: targetCollection, dimensionCollectionType: targetCollectionType });
12✔
1712
        if (targetCollectionType === PivotDimensionType.Filter) {
12✔
1713
            this.dimensionDataColumns = this.generateDimensionColumns();
3✔
1714
            this.reflow();
3✔
1715
        }
1716
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
12✔
1717
    }
1718

1719
    /**
1720
     * Move dimension from its currently collection to the specified target collection by type at specified index or at the collection's end.
1721
     *
1722
     * @example
1723
     * ```typescript
1724
     * this.grid.moveDimension(dimension, PivotDimensionType.Row, 1);
1725
     * ```
1726
     * @param dimension The dimension that will be moved.
1727
     * @param targetCollectionType The target collection type to move it to. Can be Row, Column or Filter.
1728
     * @param index The index in the collection at which to add.
1729
     * This parameter is optional. If not set it will add it to the end of the collection.
1730
     */
1731
    public moveDimension(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1732
        const prevCollectionType = this.getDimensionType(dimension);
9✔
1733
        if (prevCollectionType === null) return;
9✔
1734
        // remove from old collection
1735
        this._removeDimensionInternal(dimension);
8✔
1736
        // add to target
1737
        this.insertDimensionAt(dimension, targetCollectionType, index);
8✔
1738

1739
        if (prevCollectionType === PivotDimensionType.Column) {
8✔
1740
            this.setupColumns();
3✔
1741
        }
1742
    }
1743

1744
    /**
1745
     * Removes dimension from its currently collection.
1746
     * @remarks
1747
     * This is different than toggleDimension that enabled/disables the dimension.
1748
     * This completely removes the specified dimension from the collection.
1749
     * @example
1750
     * ```typescript
1751
     * this.grid.removeDimension(dimension);
1752
     * ```
1753
     * @param dimension The dimension to be removed.
1754
     */
1755
    public removeDimension(dimension: IPivotDimension) {
1756
        const prevCollectionType = this.getDimensionType(dimension);
4✔
1757
        this._removeDimensionInternal(dimension);
4✔
1758
        if (prevCollectionType === PivotDimensionType.Column) {
4✔
1759
            this.setupColumns();
1✔
1760
        }
1761
        if (prevCollectionType === PivotDimensionType.Filter) {
4✔
1762
            this.reflow();
1✔
1763
        }
1764
        this.pipeTrigger++;
4✔
1765
        this.cdr.detectChanges();
4✔
1766
    }
1767

1768
    /**
1769
     * Toggles the dimension's enabled state on or off.
1770
     * @remarks
1771
     * The dimension remains in its current collection. This just changes its enabled state.
1772
     * @example
1773
     * ```typescript
1774
     * this.grid.toggleDimension(dimension);
1775
     * ```
1776
     * @param dimension The dimension to be toggled.
1777
     */
1778
    public toggleDimension(dimension: IPivotDimension) {
1779
        const dimType = this.getDimensionType(dimension);
12✔
1780
        if (dimType === null) return;
12✔
1781
        const collection = this.getDimensionsByType(dimType);
11✔
1782
        dimension.enabled = !dimension.enabled;
11✔
1783
        if (dimType === PivotDimensionType.Column) {
11✔
1784
            this.setupColumns();
5✔
1785
        }
1786
        if (!dimension.enabled && dimension.filter) {
11✔
1787
            this.filteringService.clearFilter(dimension.memberName);
1✔
1788
        }
1789
        this.pipeTrigger++;
11✔
1790
        this.dimensionsChange.emit({ dimensions: collection, dimensionCollectionType: dimType });
11✔
1791
        this.cdr.detectChanges();
11✔
1792
        if (dimType === PivotDimensionType.Filter) {
11✔
1793
            this.reflow();
3✔
1794
        }
1795
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
11✔
1796
    }
1797

1798
    /**
1799
     * Inserts value at specified index or at the end.
1800
     *
1801
     * @example
1802
     * ```typescript
1803
     * this.grid.insertValueAt(value, 1);
1804
     * ```
1805
     * @param value The value definition that will be added.
1806
     * @param index The index in the collection at which to add.
1807
     * This parameter is optional. If not set it will add it to the end of the collection.
1808
     */
1809
    public insertValueAt(value: IPivotValue, index?: number) {
1810
        if (!this.pivotConfiguration.values) {
7✔
1811
            this.pivotConfiguration.values = [];
1✔
1812
        }
1813
        const values = this.pivotConfiguration.values;
7✔
1814
        if (index !== undefined) {
7✔
1815
            values.splice(index, 0, value);
6✔
1816
        } else {
1817
            values.push(value);
1✔
1818
        }
1819
        this.setupColumns();
7✔
1820
        this.pipeTrigger++;
7✔
1821
        this.cdr.detectChanges();
7✔
1822
        this.valuesChange.emit({ values });
7✔
1823
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
7✔
1824
    }
1825

1826
    /**
1827
     * Move value from its currently at specified index or at the end.
1828
     *
1829
     * @example
1830
     * ```typescript
1831
     * this.grid.moveValue(value, 1);
1832
     * ```
1833
     * @param value The value that will be moved.
1834
     * @param index The index in the collection at which to add.
1835
     * This parameter is optional. If not set it will add it to the end of the collection.
1836
     */
1837
    public moveValue(value: IPivotValue, index?: number) {
1838
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
6✔
1839
        // remove from old index
1840
        this.removeValue(value);
5✔
1841
        // add to new
1842
        this.insertValueAt(value, index);
5✔
1843
    }
1844

1845
    /**
1846
     * Removes value from collection.
1847
     * @remarks
1848
     * This is different than toggleValue that enabled/disables the value.
1849
     * This completely removes the specified value from the collection.
1850
     * @example
1851
     * ```typescript
1852
     * this.grid.removeValue(dimension);
1853
     * ```
1854
     * @param value The value to be removed.
1855
     */
1856
    public removeValue(value: IPivotValue,) {
1857
        const values = this.pivotConfiguration.values;
6✔
1858
        const currentIndex = values.indexOf(value);
6✔
1859
        if (currentIndex !== -1) {
6✔
1860
            values.splice(currentIndex, 1);
6✔
1861
            this.setupColumns();
6✔
1862
            this.pipeTrigger++;
6✔
1863
            this.valuesChange.emit({ values });
6✔
1864
            this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
6✔
1865
        }
1866
    }
1867

1868
    /**
1869
     * Toggles the value's enabled state on or off.
1870
     * @remarks
1871
     * The value remains in its current collection. This just changes its enabled state.
1872
     * @example
1873
     * ```typescript
1874
     * this.grid.toggleValue(value);
1875
     * ```
1876
     * @param value The value to be toggled.
1877
     */
1878
    public toggleValue(value: IPivotValue) {
1879
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
7✔
1880
        value.enabled = !value.enabled;
6✔
1881
        this.setupColumns();
6✔
1882
        this.pipeTrigger++;
6✔
1883
        this.valuesChange.emit({ values: this.pivotConfiguration.values });
6✔
1884
        this.reflow();
6✔
1885
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
6✔
1886
    }
1887

1888
    /**
1889
     * Sort the dimension and its children in the provided direction.
1890
     * @example
1891
     * ```typescript
1892
     * this.grid.sortDimension(dimension, SortingDirection.Asc);
1893
     * ```
1894
     * @param value The value to be toggled.
1895
     */
1896
    public sortDimension(dimension: IPivotDimension, sortDirection: SortingDirection) {
1897
        const dimensionType = this.getDimensionType(dimension);
20✔
1898
        dimension.sortDirection = sortDirection;
20✔
1899
        // apply same sort direction to children.
1900
        let dim = dimension;
20✔
1901
        if (this.pivotUI.rowLayout === PivotRowLayoutType.Vertical) {
20✔
1902
            while (dim.childLevel) {
18✔
1903
                dim.childLevel.sortDirection = dimension.sortDirection;
6✔
1904
                dim = dim.childLevel;
6✔
1905
            }
1906
        }
1907

1908
        this.pipeTrigger++;
20✔
1909
        this.dimensionsSortingExpressionsChange.emit(this.dimensionsSortingExpressions);
20✔
1910
        if (dimensionType === PivotDimensionType.Column) {
20✔
1911
            this.setupColumns();
13✔
1912
        }
1913
        this.cdr.detectChanges();
20✔
1914
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
20✔
1915
    }
1916

1917
    /**
1918
     * Filters a single `IPivotDimension`.
1919
     *
1920
     * @example
1921
     * ```typescript
1922
     * public filter() {
1923
     *      const set = new Set();
1924
     *      set.add('Value 1');
1925
     *      set.add('Value 2');
1926
     *      this.grid1.filterDimension(this.pivotConfigHierarchy.rows[0], set, IgxStringFilteringOperand.instance().condition('in'));
1927
     * }
1928
     * ```
1929
     */
1930
    public filterDimension(dimension: IPivotDimension, value: any, conditionOrExpressionTree?: IFilteringOperation | IFilteringExpressionsTree) {
1931
        this.filteringService.filter(dimension.memberName, value, conditionOrExpressionTree);
2✔
1932
        const dimensionType = this.getDimensionType(dimension);
2✔
1933
        if (dimensionType === PivotDimensionType.Column) {
2✔
1934
            this.setupColumns();
1✔
1935
        }
1936
        this.cdr.detectChanges();
2✔
1937
    }
1938

1939
    /**
1940
     * @hidden @internal
1941
     */
1942
    public getRowDimensionByName(memberName: string) {
1943
        const visibleRows = this.pivotUI.rowLayout === PivotRowLayoutType.Vertical ?
15,908✔
1944
         this.pivotConfiguration.rows :
1945
         PivotUtil.flatten(this.pivotConfiguration.rows);
1946
        const dimIndex = visibleRows.findIndex((target) => target.memberName === memberName);
27,642✔
1947
        const dim = visibleRows[dimIndex];
15,908✔
1948
        return dim;
15,908✔
1949
    }
1950

1951
    /**
1952
     * @hidden @internal
1953
     */
1954
    public getDimensionsByType(dimension: PivotDimensionType) {
1955
        switch (dimension) {
43✔
1956
            case PivotDimensionType.Row:
1957
                if (!this.pivotConfiguration.rows) {
15!
1958
                    this.pivotConfiguration.rows = [];
×
1959
                }
1960
                return this.pivotConfiguration.rows;
15✔
1961
            case PivotDimensionType.Column:
1962
                if (!this.pivotConfiguration.columns) {
16!
1963
                    this.pivotConfiguration.columns = [];
×
1964
                }
1965
                return this.pivotConfiguration.columns;
16✔
1966
            case PivotDimensionType.Filter:
1967
                if (!this.pivotConfiguration.filters) {
11✔
1968
                    this.pivotConfiguration.filters = [];
2✔
1969
                }
1970
                return this.pivotConfiguration.filters;
11✔
1971
            default:
1972
                return null;
1✔
1973
        }
1974
    }
1975

1976
    /**
1977
     * @hidden @internal
1978
     */
1979
    public resizeRowDimensionPixels(dimension: IPivotDimension, newWidth: number) {
1980
        const isPercentageWidth = dimension.width && typeof dimension.width === 'string' && dimension.width.indexOf('%') !== -1;
5✔
1981
        if (isPercentageWidth) {
5✔
1982
            dimension.width = this.reverseDimensionWidthToPercent(newWidth).toFixed(2) + '%';
1✔
1983
        } else {
1984
            dimension.width = newWidth + 'px';
4✔
1985
        }
1986

1987
        // Notify the grid to reflow, to update if horizontal scrollbar needs to be rendered/removed.
1988
        this.pipeTrigger++;
5✔
1989
        this.cdr.detectChanges();
5✔
1990
    }
1991

1992
    /*
1993
    * @hidden
1994
    * @internal
1995
    */
1996
    protected _removeDimensionInternal(dimension) {
1997
        const prevCollectionType = this.getDimensionType(dimension);
12✔
1998
        if (prevCollectionType === null) return;
12✔
1999
        const prevCollection = this.getDimensionsByType(prevCollectionType);
11✔
2000
        const currentIndex = prevCollection.indexOf(dimension);
11✔
2001
        prevCollection.splice(currentIndex, 1);
11✔
2002
        this.pipeTrigger++;
11✔
2003
        this.cdr.detectChanges();
11✔
2004
    }
2005

2006
    protected getDimensionType(dimension: IPivotDimension): PivotDimensionType {
2007
        return PivotUtil.flatten(this.pivotConfiguration.rows).indexOf(dimension) !== -1 ? PivotDimensionType.Row :
61✔
2008
            PivotUtil.flatten(this.pivotConfiguration.columns).indexOf(dimension) !== -1 ? PivotDimensionType.Column :
40✔
2009
                (!!this.pivotConfiguration.filters && PivotUtil.flatten(this.pivotConfiguration.filters).indexOf(dimension) !== -1) ?
39✔
2010
                    PivotDimensionType.Filter : null;
2011
    }
2012

2013
    protected getPivotRowHeaderContentWidth(headerGroup: IgxPivotRowHeaderGroupComponent) {
2014
        const headerSizes = this.getHeaderCellWidth(headerGroup.header.refInstance.nativeElement);
×
2015
        return headerSizes.width + headerSizes.padding;
×
2016
    }
2017

2018
    protected getLargesContentWidth(contents: ElementRef[]): string {
2019
        const largest = new Map<number, number>();
2✔
2020
        if (contents.length > 0) {
2✔
2021
            const cellsContentWidths = [];
2✔
2022
            contents.forEach((elem) => {
2✔
2023
                elem instanceof IgxPivotRowHeaderGroupComponent ?
10!
2024
                    cellsContentWidths.push(this.getPivotRowHeaderContentWidth(elem)) :
2025
                    cellsContentWidths.push(this.getHeaderCellWidth(elem.nativeElement).width);
2026
            });
2027
            const index = cellsContentWidths.indexOf(Math.max(...cellsContentWidths));
2✔
2028
            const cellStyle = this.document.defaultView.getComputedStyle(contents[index].nativeElement);
2✔
2029
            const cellPadding = parseFloat(cellStyle.paddingLeft) + parseFloat(cellStyle.paddingRight) +
2✔
2030
                parseFloat(cellStyle.borderLeftWidth) + parseFloat(cellStyle.borderRightWidth);
2031
            largest.set(Math.max(...cellsContentWidths), cellPadding);
2✔
2032
        }
2033
        const largestCell = Math.max(...Array.from(largest.keys()));
2✔
2034
        const width = Math.ceil(largestCell + largest.get(largestCell));
2✔
2035

2036
        if (Number.isNaN(width)) {
2!
2037
            return null;
×
2038
        } else {
2039
            return width + 'px';
2✔
2040
        }
2041
    }
2042

2043
    /** @hidden @internal */
2044
    public get hasHorizontalLayout() {
2045
        return this.pivotUI.rowLayout === PivotRowLayoutType.Horizontal;
101,454✔
2046
    }
2047

2048
    /**
2049
    * @hidden
2050
    */
2051
    public get hasMultipleValues() {
2052
        return this.values.length > 1;
172,055✔
2053
    }
2054

2055
    /**
2056
    * @hidden
2057
    */
2058
    public get excelStyleFilterMaxHeight() {
2059
        // max 10 rows, row size depends on grid size
2060
        const maxHeight = this.renderedRowHeight * 10;
4,301✔
2061
        return `${maxHeight}px`;
4,301✔
2062
    }
2063

2064
    /**
2065
    * @hidden
2066
    */
2067
    public get excelStyleFilterMinHeight(): string {
2068
        // min 5 rows, row size depends on grid size
2069
        const minHeight = this.renderedRowHeight * 5;
4,301✔
2070
        return `${minHeight}px`;
4,301✔
2071
    }
2072

2073
    /** @hidden @internal */
2074
    public override get activeDescendant() {
2075
        const activeElem = this.navigation.activeNode;
4,304✔
2076
        if ((this.navigation as IgxPivotGridNavigationService).isRowHeaderActive ||
4,304✔
2077
            (this.navigation as IgxPivotGridNavigationService).isRowDimensionHeaderActive) {
2078
            if (!activeElem || !Object.keys(activeElem).length) {
198!
2079
                return this.id;
×
2080
            }
2081

2082
            return `${this.id}_${activeElem.row}_${activeElem.column}`;
198✔
2083
        }
2084

2085
        return super.activeDescendant;
4,106✔
2086
    }
2087

2088
    protected resolveToggle(groupColumn: IgxColumnComponent, state: boolean) {
2089
        if (!groupColumn) return;
8!
2090
        groupColumn.hidden = state;
8✔
2091
        this.columnGroupStates.set(groupColumn.field, state);
8✔
2092
        const childrenTotal = this.hasMultipleValues ?
8✔
2093
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === this.values.length) :
44✔
2094
            groupColumn.children.filter(x => !x.columnGroup);
3✔
2095
        const childrenSubgroups = this.hasMultipleValues ?
8✔
2096
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === 0) :
44✔
2097
            groupColumn.children.filter(x => x.columnGroup);
3✔
2098
        childrenTotal.forEach(group => {
8✔
2099
            const newState = this.columnGroupStates.get(group.field) || state;
18✔
2100
            if (newState) {
18✔
2101
                group.headerTemplate = this.headerTemplate;
11✔
2102
            } else {
2103
                group.headerTemplate = undefined;
7✔
2104
            }
2105
        });
2106
        if (!groupColumn.hidden && childrenSubgroups.length > 0) {
8✔
2107
            childrenSubgroups.forEach(group => {
1✔
2108
                const newState = this.columnGroupStates.get(group.field) || state;
3✔
2109
                this.resolveToggle(group, newState);
3✔
2110
            });
2111
        }
2112
    }
2113

2114
    protected override buildDataView(data: any[]) {
2115
        this._dataView = data;
389✔
2116
    }
2117

2118
    /**
2119
     * @hidden @internal
2120
     */
2121
    protected override getDataBasedBodyHeight(): number {
2122
        const dvl = this.dataView?.length || 0;
81!
2123
        return dvl < this._defaultTargetRecordNumber ? 0 : this.defaultTargetBodyHeight;
81✔
2124
    }
2125

2126
    protected override horizontalScrollHandler(event) {
2127
        const scrollLeft = event.target.scrollLeft;
2✔
2128
        this.theadRow.headerContainers.forEach(headerForOf => {
2✔
2129
            headerForOf.onHScroll(scrollLeft);
4✔
2130
        });
2131
        super.horizontalScrollHandler(event);
2✔
2132
    }
2133

2134
    protected override verticalScrollHandler(event) {
2135
        this.verticalRowDimScrollContainers.forEach(x => {
×
2136
            x.onScroll(event);
×
2137
        });
2138
        super.verticalScrollHandler(event);
×
2139
    }
2140

2141
    /**
2142
     * @hidden
2143
     */
2144
    protected override autogenerateColumns() {
2145
        let columns = [];
247✔
2146
        const data = this.gridAPI.filterDataByExpressions(this.filteringExpressionsTree);
247✔
2147
        this.dimensionDataColumns = this.generateDimensionColumns();
247✔
2148
        const flattenedColumnsWithSorting = PivotUtil.flatten(this.columnDimensions).filter(dim => dim.sortDirection);
248✔
2149
        const expressions = flattenedColumnsWithSorting.length > 0 ? PivotSortUtil.generateDimensionSortingExpressions(flattenedColumnsWithSorting) : [];
247✔
2150
        let sortedData = data;
247✔
2151
        if (expressions.length > 0) {
247✔
2152
            sortedData = DataUtil.sort(cloneArray(data), expressions, this.sortStrategy, this);
12✔
2153
        }
2154
        let fieldsMap;
2155
        if (this.pivotConfiguration.columnStrategy && this.pivotConfiguration.columnStrategy instanceof NoopPivotDimensionsStrategy) {
247✔
2156
            const fields = this.generateDataFields(sortedData);
5✔
2157
            if (fields.length === 0) return;
5✔
2158
            const rowFields = PivotUtil.flatten(this.pivotConfiguration.rows).map(x => x.memberName);
6✔
2159
            const keyFields = Object.values(this.pivotKeys);
3✔
2160
            const filteredFields = fields.filter(x => rowFields.indexOf(x) === -1 && keyFields.indexOf(x) === -1 &&
18✔
2161
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.level) === -1 &&
2162
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.records) === -1);
2163
            fieldsMap = this.generateFromData(filteredFields);
3✔
2164
        } else {
2165
            fieldsMap = PivotUtil.getFieldsHierarchy(
242✔
2166
                sortedData,
2167
                this.columnDimensions,
2168
                PivotDimensionType.Column,
2169
                this.pivotKeys,
2170
                this.pivotValueCloneStrategy
2171
            );
2172
        }
2173
        columns = this.generateColumnHierarchy(fieldsMap, sortedData);
245✔
2174
        this._autoGeneratedCols = columns;
245✔
2175
        // reset expansion states if any are stored.
2176
        this.columnGroupStates.forEach((value, key) => {
245✔
2177
            if (value) {
1✔
2178
                const primaryColumn = columns.find(x => x.field === key && x.headerTemplate === this.headerTemplate);
1✔
2179
                const groupSummaryColumn = columns.find(x => x.field === key && x.headerTemplate !== this.headerTemplate);
14✔
2180
                this.toggleRowGroup(primaryColumn, value);
1✔
2181
                if (groupSummaryColumn) {
1✔
2182
                    groupSummaryColumn.headerTemplate = this.headerTemplate;
1✔
2183
                }
2184
            }
2185
        });
2186

2187
        this.updateColumns(columns);
245✔
2188
        this.pipeTrigger++;
245✔
2189
        this.reflow();
245✔
2190
    }
2191

2192
    protected generateDimensionColumns(): IgxColumnComponent[] {
2193
        const columns = [];
280✔
2194
        this.allVisibleDimensions.forEach((dim) => {
280✔
2195
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
779✔
2196
            ref.instance.field = dim.memberName;
779✔
2197
            ref.instance.header = dim.displayName || dim.memberName;
779✔
2198
            ref.instance.headerTemplate = this.rowDimensionHeaderTemplate;
779✔
2199
            ref.instance.resizable = this.rowDimensionResizing;
779✔
2200
            ref.instance.sortable = dim.sortable === undefined ? true : dim.sortable;
779!
2201
            ref.instance.width = this.rowDimensionWidth(dim);
779✔
2202
            ref.changeDetectorRef.detectChanges();
779✔
2203
            columns.push(ref.instance);
779✔
2204
        });
2205
        return columns;
280✔
2206
    }
2207

2208
    protected override calculateGridSizes(recalcFeatureWidth = true) {
497✔
2209
        super.calculateGridSizes(recalcFeatureWidth);
497✔
2210
        if (this.hasDimensionsToAutosize) {
497✔
2211
            this.cdr.detectChanges();
2✔
2212
            this.zone.onStable.pipe(first()).subscribe(() => {
2✔
2213
                requestAnimationFrame(() => {
2✔
2214
                    this.autoSizeDimensionsInView();
2✔
2215
                });
2216
            });
2217
        }
2218
    }
2219

2220
    protected getContentCollection(dimenstion: IPivotDimension) {
2221
        let contentCollection;
2222
        if (this.hasHorizontalLayout) {
3!
2223
            const allMrlContents = this.rowDimensionMrlRowsCollection.map(mrlRow => mrlRow.contentCells.toArray()).flat();
×
2224
            contentCollection = allMrlContents.filter(cell => cell.rootDimension === dimenstion);
×
2225
        } else {
2226
            contentCollection = this.rowDimensionContentCollection.toArray();
3✔
2227
        }
2228
        return contentCollection;
3✔
2229
    }
2230

2231
    protected autoSizeDimensionsInView() {
2232
        if (!this.hasDimensionsToAutosize) return;
2✔
2233
        for (const dim of this.visibleRowDimensions) {
1✔
2234
            if (dim.width === 'auto') {
1✔
2235
                const contentWidths = [];
1✔
2236
                const relatedDims = PivotUtil.flatten([dim]).map(x => x.memberName);
2✔
2237
                const contentCollection = this.getContentCollection(dim);
1✔
2238
                const content = contentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
5✔
2239
                const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
5✔
2240
                headers.forEach((header) => contentWidths.push(header?.nativeElement?.offsetWidth || 0));
5!
2241
                if (this.pivotUI.showRowHeaders) {
1!
2242
                    const dimensionHeader = this.theadRow.rowDimensionHeaders.find(x => x.column.field === dim.memberName);
×
2243
                    contentWidths.push(parseFloat(this.getLargesContentWidth([dimensionHeader])));
×
2244
                }
2245
                const max = Math.max(...contentWidths);
1✔
2246
                if (max === 0) {
1!
2247
                    // cells not in DOM yet...
2248
                    continue;
×
2249
                }
2250
                const maxSize = Math.ceil(Math.max(...contentWidths));
1✔
2251
                dim.autoWidth = maxSize;
1✔
2252
            }
2253
        }
2254

2255
        if (this.isColumnWidthSum) {
1!
2256
            this.calcWidth = this.getColumnWidthSum();
×
2257
        }
2258
    }
2259

2260
    /** @hidden @internal */
2261
    public get hasDimensionsToAutosize() {
2262
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
693✔
2263
    }
2264

2265
    protected generateFromData(fields: string[]) {
2266
        const separator = this.pivotKeys.columnDimensionSeparator;
3✔
2267
        const dataArr = fields.map(x => x.split(separator)).sort(x => x.length);
12✔
2268
        const hierarchy = new Map<string, any>();
3✔
2269
        const columnDimensions =  PivotUtil.flatten(this.columnDimensions);
3✔
2270
        dataArr.forEach(arr => {
3✔
2271
            let currentHierarchy = hierarchy;
12✔
2272
            const path = [];
12✔
2273
            let index = 0;
12✔
2274
            for (const val of arr) {
12✔
2275
                path.push(val);
12✔
2276
                const newPath = path.join(separator);
12✔
2277
                let targetHierarchy = currentHierarchy.get(newPath);
12✔
2278
                if (!targetHierarchy) {
12✔
2279
                    const currentColumnDimension = columnDimensions[index];
12✔
2280
                    currentHierarchy.set(newPath, { value: newPath, expandable: !!currentColumnDimension.childLevel, children: new Map<string, any>(), dimension: currentColumnDimension });
12✔
2281
                    targetHierarchy = currentHierarchy.get(newPath);
12✔
2282
                }
2283
                currentHierarchy = targetHierarchy.children;
12✔
2284
                index++;
12✔
2285
            }
2286
        });
2287
        return hierarchy;
3✔
2288
    }
2289

2290
    protected generateColumnHierarchy(fields: Map<string, any>, data, parent = null): IgxColumnComponent[] {
245✔
2291
        let columns = [];
309✔
2292
        if (fields.size === 0) {
309✔
2293
            this.values.forEach((value) => {
20✔
2294
                const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
21✔
2295
                ref.instance.header = value.displayName;
21✔
2296
                ref.instance.field = value.member;
21✔
2297
                ref.instance.parent = parent;
21✔
2298
                ref.instance.sortable = true;
21✔
2299
                ref.instance.dataType = value.dataType || this.resolveDataTypes(data.length ? data[0][value.member] : null);
21!
2300
                ref.instance.formatter = value.formatter;
21✔
2301
                columns.push(ref.instance);
21✔
2302
            });
2303
            return columns;
20✔
2304
        }
2305
        const currentFields = fields;
289✔
2306
        currentFields.forEach((value) => {
289✔
2307
            let shouldGenerate = true;
985✔
2308
            if (data.length === 0) {
985!
2309
                shouldGenerate = false;
×
2310
            }
2311
            if (shouldGenerate && (value.children == null || value.children.length === 0 || value.children.size === 0)) {
985✔
2312
                const col = this.createColumnForDimension(value, data, parent, this.hasMultipleValues);
921✔
2313
                columns.push(col);
921✔
2314
                if (this.hasMultipleValues) {
921✔
2315
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
750✔
2316
                    col.children.reset(measureChildren);
750✔
2317
                    columns = columns.concat(measureChildren);
750✔
2318
                }
2319

2320
            } else if (shouldGenerate) {
64✔
2321
                const col = this.createColumnForDimension(value, data, parent, true);
64✔
2322
                if (value.expandable) {
64✔
2323
                    col.headerTemplate = this.headerTemplate;
21✔
2324
                }
2325
                const children = this.generateColumnHierarchy(value.children, data, col);
64✔
2326
                const filteredChildren = children.filter(x => x.level === col.level + 1);
456✔
2327
                columns.push(col);
64✔
2328
                if (this.hasMultipleValues) {
64✔
2329
                    let measureChildren = this.getMeasureChildren(data, col, true, value.dimension.width);
63✔
2330
                    const nestedChildren = filteredChildren;
63✔
2331
                    //const allChildren = children.concat(measureChildren);
2332
                    col.children.reset(nestedChildren);
63✔
2333
                    columns = columns.concat(children);
63✔
2334
                    if (value.dimension.childLevel) {
63✔
2335
                        const sibling = this.createColumnForDimension(value, data, parent, true);
20✔
2336
                        columns.push(sibling);
20✔
2337

2338
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2339
                        sibling.children.reset(measureChildren);
20✔
2340
                        columns = columns.concat(measureChildren);
20✔
2341
                    }
2342

2343
                } else {
2344
                    col.children.reset(filteredChildren);
1✔
2345
                    columns = columns.concat(children);
1✔
2346
                    if (value.dimension.childLevel) {
1✔
2347
                        const sibling = this.createColumnForDimension(value, data, parent, false);
1✔
2348
                        columns.push(sibling);
1✔
2349
                    }
2350
                }
2351
            }
2352
        });
2353

2354
        return columns;
289✔
2355
    }
2356

2357

2358
    protected generateConfig() {
2359
        if (!this.data) return;
1!
2360

2361
        const data = this.data;
1✔
2362
        const fields = this.generateDataFields(data);
1✔
2363
        const columnDimensions: IPivotDimension[] = [];
1✔
2364
        const rowDimensions: IPivotDimension[] = [];
1✔
2365
        const values: IPivotValue[] = [];
1✔
2366
        let isFirstDate = true;
1✔
2367
        fields.forEach((field) => {
1✔
2368
            const dataType = this.resolveDataTypes(data[0][field]);
6✔
2369
            switch (dataType) {
6✔
2370
                case "number":
2371
                    {
2372
                        const value: IPivotValue = {
2✔
2373
                            member: field,
2374
                            displayName: field,
2375
                            dataType: dataType,
2376
                            aggregate: {
2377
                                key: 'sum',
2378
                                label: 'Sum',
2379
                                aggregatorName: "SUM"
2380
                            },
2381
                            enabled: true
2382
                        };
2383
                        values.push(value);
2✔
2384
                        break;
2✔
2385
                }
2386
            case "date":
2387
            {
2388
                const dimension: IPivotDimension = new IgxPivotDateDimension(
1✔
2389
                    {
2390
                        memberName: field,
2391
                        enabled: isFirstDate,
2392
                        dataType: dataType
2393
                    }
2394
                )
2395
                rowDimensions.push(dimension);
1✔
2396
                isFirstDate = false;
1✔
2397
                break;
1✔
2398
            }
2399
                default: {
2400
                    const dimension: IPivotDimension = {
3✔
2401
                        memberName: field,
2402
                        enabled: false,
2403
                        dataType: dataType
2404
                    };
2405
                    columnDimensions.push(dimension);
3✔
2406
                    break;
3✔
2407
                }
2408
            }
2409
        });
2410
        const config: IPivotConfiguration = {
1✔
2411
            columns: columnDimensions,
2412
            rows: rowDimensions,
2413
            values: values
2414
        };
2415
        this.pivotConfiguration = config;
1✔
2416
    }
2417

2418
    protected createColumnForDimension(value: any, data: any, parent: ColumnType, isGroup: boolean) {
2419
        const key = value.value;
1,006✔
2420
        const ref = isGroup ?
1,006✔
2421
            createComponent(IgxColumnGroupComponent, { environmentInjector: this.envInjector, elementInjector: this.injector }) :
2422
            createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2423
        ref.instance.header = parent != null ? key.split(parent.header + this.pivotKeys.columnDimensionSeparator)[1] : key;
1,006✔
2424
        ref.instance.field = key;
1,006✔
2425
        ref.instance.parent = parent;
1,006✔
2426
        if (value.dimension.width) {
1,006!
2427
            ref.instance.width = value.dimension.width;
×
2428
        }
2429
        const valueDefinition = this.values[0];
1,006✔
2430
        ref.instance.dataType = valueDefinition?.dataType || this.resolveDataTypes(data[0][valueDefinition?.member]);
1,006✔
2431
        ref.instance.formatter = valueDefinition?.formatter;
1,006✔
2432
        ref.instance.sortable = true;
1,006✔
2433
        ref.changeDetectorRef.detectChanges();
1,006✔
2434
        return ref.instance;
1,006✔
2435
    }
2436

2437
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2438
        if (dim.width) {
×
2439
            return dim.width;
×
2440
        }
2441
        return this.minColumnWidth + 'px';
×
2442
    }
2443

2444
    protected getMeasureChildren(data, parent, hidden, parentWidth) {
2445
        const cols = [];
833✔
2446
        const count = this.values.length;
833✔
2447
        const childWidth = parseInt(parentWidth, 10) / count;
833✔
2448
        const isPercent = parentWidth && parentWidth.indexOf('%') !== -1;
833!
2449
        const isAuto = parentWidth && parentWidth.indexOf('auto') !== -1;
833!
2450
        this.values.forEach(val => {
833✔
2451
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
1,671✔
2452
            ref.instance.header = val.displayName || val.member;
1,671✔
2453
            ref.instance.field = parent.field + this.pivotKeys.columnDimensionSeparator + val.member;
1,671✔
2454
            ref.instance.parent = parent;
1,671✔
2455
            if (parentWidth) {
1,671!
2456
                ref.instance.width = isAuto ? 'auto' : isPercent ? childWidth + '%' : childWidth + 'px';
×
2457
            }
2458
            ref.instance.hidden = hidden;
1,671✔
2459
            ref.instance.sortable = this._sortableColumns;
1,671✔
2460
            ref.instance.dataType = val.dataType || this.resolveDataTypes(data[0][val.member]);
1,671✔
2461
            ref.instance.formatter = val.formatter;
1,671✔
2462
            ref.changeDetectorRef.detectChanges();
1,671✔
2463
            cols.push(ref.instance);
1,671✔
2464
        });
2465
        return cols;
833✔
2466
    }
2467

2468
    /**
2469
    * @hidden @internal
2470
    */
2471
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2472
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2473

2474
    /**
2475
     * Gets/Sets a custom template when pivot grid is empty.
2476
     *
2477
     * @example
2478
     * ```html
2479
     * <igx-pivot-grid [emptyPivotGridTemplate]="myTemplate"><igx-pivot-grid>
2480
     * ```
2481
     */
2482
    @Input()
2483
    public emptyPivotGridTemplate: TemplateRef<void>;
2484

2485
    /**
2486
    * @hidden @internal
2487
    */
2488
    public override get template(): TemplateRef<any> {
2489
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
2,152✔
2490
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
2,152✔
2491
            // no enabled values and dimensions
2492
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
55✔
2493
        }
2494
        return super.template;
2,097✔
2495
    }
2496

2497
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2498
        const dimensions = PivotUtil.flatten(this.allDimensions);
156✔
2499
        dimensions.forEach(dim => {
156✔
2500
            this.dimensionInit.emit(dim);
546✔
2501
        });
2502
        const values = pivotConfig?.values;
156✔
2503
        values?.forEach(val => {
156✔
2504
            this.valueInit.emit(val);
274✔
2505
        });
2506
    }
2507

2508
    protected rowDimensionByName(memberName: string) {
2509
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2510
    }
2511

2512
    protected calculateResizerTop() {
2513
        return this.pivotUI.showRowHeaders ?
18✔
2514
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
8!
2515
            this.theadRow.nativeElement.offsetHeight;
2516
    }
2517

2518
    protected override updateDefaultRowHeight() {
2519
        super.updateDefaultRowHeight();
193✔
2520
        if (this.hasHorizontalLayout) {
193✔
2521
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2522
            this.regroupTrigger++;
12✔
2523
        }
2524
    }
2525

2526
    /**
2527
     * @hidden @internal
2528
     */
2529
    public createRow(index: number, data?: any): RowType {
2530
        let row: RowType;
2531

NEW
2532
        const dataIndex = this._getDataViewIndex(index);
×
NEW
2533
        const rec = data ?? this.dataView[dataIndex];
×
2534

2535

NEW
2536
        if (!row && rec) {
×
NEW
2537
            row = new IgxPivotGridRow(this, index, rec);
×
2538
        }
NEW
2539
        return row;
×
2540
    }
2541
}
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