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

IgniteUI / igniteui-angular / 15971681234

30 Jun 2025 11:28AM UTC coverage: 91.634% (-0.007%) from 91.641%
15971681234

push

github

web-flow
refactoring(query-builder): expose the outer padding as a css variable (#15974)

13453 of 15747 branches covered (85.43%)

27055 of 29525 relevant lines covered (91.63%)

37003.62 hits per line

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

89.38
/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
} from '@angular/core';
32
import { DOCUMENT, NgTemplateOutlet, NgClass, NgStyle } from '@angular/common';
33

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

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

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

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

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

229

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

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

256

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

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

283

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

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

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

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

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

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

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

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

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

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

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

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

393

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

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

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

421

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

777

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

889

890

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1007
        });
1008

1009
        return selectedRowIds;
15✔
1010
    }
1011

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2264
    protected generateFromData(fields: string[]) {
2265
        const separator = this.pivotKeys.columnDimensionSeparator;
3✔
2266
        const dataArr = fields.map(x => x.split(separator)).sort(x => x.length);
12✔
2267
        const hierarchy = new Map<string, any>();
3✔
2268
        const columnDimensions = PivotUtil.flatten(this.columnDimensions);
3✔
2269
        dataArr.forEach(arr => {
3✔
2270
            let currentHierarchy = hierarchy;
12✔
2271
            const path = [];
12✔
2272
            let index = 0;
12✔
2273
            for (const val of arr) {
12✔
2274
                path.push(val);
12✔
2275
                const newPath = path.join(separator);
12✔
2276
                let targetHierarchy = currentHierarchy.get(newPath);
12✔
2277
                if (!targetHierarchy) {
12✔
2278
                    const currentColumnDimension = columnDimensions[index];
12✔
2279
                    currentHierarchy.set(newPath, { value: newPath, expandable: !!currentColumnDimension.childLevel, children: new Map<string, any>(), dimension: currentColumnDimension });
12✔
2280
                    targetHierarchy = currentHierarchy.get(newPath);
12✔
2281
                }
2282
                currentHierarchy = targetHierarchy.children;
12✔
2283
                index++;
12✔
2284
            }
2285
        });
2286
        return hierarchy;
3✔
2287
    }
2288
    protected generateColumnHierarchy(fields: Map<string, any>, data, parent = null): IgxColumnComponent[] {
245✔
2289
        let columns = [];
309✔
2290
        if (fields.size === 0) {
309✔
2291
            this.values.forEach((value) => {
20✔
2292
                const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
21✔
2293
                let columnDataType = value.dataType || this.resolveDataTypes(data.length ? data[0][value.member] : null);
21!
2294

2295
                if (value.aggregate?.key?.toLowerCase() === 'count' && (columnDataType === GridColumnDataType.Currency || columnDataType == GridColumnDataType.Percent)) {
21!
2296
                    columnDataType = GridColumnDataType.Number;
×
2297
                }
2298

2299
                ref.instance.header = value.displayName;
21✔
2300
                ref.instance.field = value.member;
21✔
2301
                ref.instance.parent = parent;
21✔
2302
                ref.instance.sortable = true;
21✔
2303
                ref.instance.dataType = columnDataType;
21✔
2304
                ref.instance.formatter = value.formatter;
21✔
2305
                columns.push(ref.instance);
21✔
2306
            });
2307
            return columns;
20✔
2308
        }
2309
        const currentFields = fields;
289✔
2310
        currentFields.forEach((value) => {
289✔
2311
            let shouldGenerate = true;
985✔
2312
            if (data.length === 0) {
985!
2313
                shouldGenerate = false;
×
2314
            }
2315
            if (shouldGenerate && (value.children == null || value.children.length === 0 || value.children.size === 0)) {
985✔
2316
                const col = this.createColumnForDimension(value, data, parent, this.hasMultipleValues);
921✔
2317

2318
                if (!this.hasMultipleValues && this.values.length > 0) {
921✔
2319
                    PivotUtil.updateColumnTypeByAggregator([col], this.values[0], true);
160✔
2320
                }
2321

2322
                columns.push(col);
921✔
2323
                if (this.hasMultipleValues) {
921✔
2324
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
750✔
2325

2326
                    measureChildren.forEach((child, index) => {
750✔
2327
                        const pivotValue = this.values[index];
1,505✔
2328
                        PivotUtil.updateColumnTypeByAggregator([child], pivotValue, this.values.length === 1);
1,505✔
2329
                    });
2330

2331
                    col.children.reset(measureChildren);
750✔
2332
                    columns = columns.concat(measureChildren);
750✔
2333
                }
2334

2335
            } else if (shouldGenerate) {
64✔
2336
                const col = this.createColumnForDimension(value, data, parent, true);
64✔
2337
                if (value.expandable) {
64✔
2338
                    col.headerTemplate = this.headerTemplate;
21✔
2339
                }
2340
                const children = this.generateColumnHierarchy(value.children, data, col);
64✔
2341
                const filteredChildren = children.filter(x => x.level === col.level + 1);
456✔
2342
                columns.push(col);
64✔
2343
                if (this.hasMultipleValues) {
64✔
2344
                    let measureChildren = this.getMeasureChildren(data, col, true, value.dimension.width);
63✔
2345
                    const nestedChildren = filteredChildren;
63✔
2346
                    //const allChildren = children.concat(measureChildren);
2347
                    col.children.reset(nestedChildren);
63✔
2348
                    columns = columns.concat(children);
63✔
2349
                    if (value.dimension.childLevel) {
63✔
2350
                        const sibling = this.createColumnForDimension(value, data, parent, true);
20✔
2351
                        columns.push(sibling);
20✔
2352

2353
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2354
                        sibling.children.reset(measureChildren);
20✔
2355
                        columns = columns.concat(measureChildren);
20✔
2356
                    }
2357

2358
                } else {
2359
                    col.children.reset(filteredChildren);
1✔
2360
                    columns = columns.concat(children);
1✔
2361
                    if (value.dimension.childLevel) {
1✔
2362
                        const sibling = this.createColumnForDimension(value, data, parent, false);
1✔
2363
                        columns.push(sibling);
1✔
2364
                    }
2365
                }
2366
            }
2367
        });
2368

2369
        return columns;
289✔
2370
    }
2371

2372

2373
    protected generateConfig() {
2374
        if (!this.data) return;
1!
2375

2376
        const data = this.data;
1✔
2377
        const fields = this.generateDataFields(data);
1✔
2378
        const columnDimensions: IPivotDimension[] = [];
1✔
2379
        const rowDimensions: IPivotDimension[] = [];
1✔
2380
        const values: IPivotValue[] = [];
1✔
2381
        let isFirstDate = true;
1✔
2382
        fields.forEach((field) => {
1✔
2383
            const dataType = this.resolveDataTypes(data[0][field]);
6✔
2384
            switch (dataType) {
6✔
2385
                case "number":
2386
                    {
2387
                        const value: IPivotValue = {
2✔
2388
                            member: field,
2389
                            displayName: field,
2390
                            dataType: dataType,
2391
                            aggregate: {
2392
                                key: 'sum',
2393
                                label: 'Sum',
2394
                                aggregatorName: "SUM"
2395
                            },
2396
                            enabled: true
2397
                        };
2398
                        values.push(value);
2✔
2399
                        break;
2✔
2400
                    }
2401
                case "date":
2402
                    {
2403
                        const dimension: IPivotDimension = new IgxPivotDateDimension(
1✔
2404
                            {
2405
                                memberName: field,
2406
                                enabled: isFirstDate,
2407
                                dataType: dataType
2408
                            }
2409
                        )
2410
                        rowDimensions.push(dimension);
1✔
2411
                        isFirstDate = false;
1✔
2412
                        break;
1✔
2413
                    }
2414
                default: {
2415
                    const dimension: IPivotDimension = {
3✔
2416
                        memberName: field,
2417
                        enabled: false,
2418
                        dataType: dataType
2419
                    };
2420
                    columnDimensions.push(dimension);
3✔
2421
                    break;
3✔
2422
                }
2423
            }
2424
        });
2425
        const config: IPivotConfiguration = {
1✔
2426
            columns: columnDimensions,
2427
            rows: rowDimensions,
2428
            values: values
2429
        };
2430
        this.pivotConfiguration = config;
1✔
2431
    }
2432

2433
    protected createColumnForDimension(value: any, data: any, parent: ColumnType, isGroup: boolean) {
2434
        const key = value.value;
1,006✔
2435
        const ref = isGroup ?
1,006✔
2436
            createComponent(IgxColumnGroupComponent, { environmentInjector: this.envInjector, elementInjector: this.injector }) :
2437
            createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2438
        ref.instance.header = parent != null ? key.split(parent.header + this.pivotKeys.columnDimensionSeparator)[1] : key;
1,006✔
2439
        ref.instance.field = key;
1,006✔
2440
        ref.instance.parent = parent;
1,006✔
2441
        if (value.dimension.width) {
1,006!
2442
            ref.instance.width = value.dimension.width;
×
2443
        }
2444
        const valueDefinition = this.values[0];
1,006✔
2445
        ref.instance.dataType = valueDefinition?.dataType || this.resolveDataTypes(data[0][valueDefinition?.member]);
1,006✔
2446
        ref.instance.formatter = valueDefinition?.formatter;
1,006✔
2447
        ref.instance.sortable = true;
1,006✔
2448
        ref.changeDetectorRef.detectChanges();
1,006✔
2449
        return ref.instance;
1,006✔
2450
    }
2451

2452
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2453
        if (dim.width) {
×
2454
            return dim.width;
×
2455
        }
2456
        return this.minColumnWidth + 'px';
×
2457
    }
2458

2459
    protected getMeasureChildren(data, parent, hidden, parentWidth) {
2460
        const cols = [];
833✔
2461
        const count = this.values.length;
833✔
2462
        const childWidth = parseInt(parentWidth, 10) / count;
833✔
2463
        const isPercent = parentWidth && parentWidth.indexOf('%') !== -1;
833!
2464
        const isAuto = parentWidth && parentWidth.indexOf('auto') !== -1;
833!
2465
        this.values.forEach(val => {
833✔
2466
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
1,671✔
2467
            ref.instance.header = val.displayName || val.member;
1,671✔
2468
            ref.instance.field = parent.field + this.pivotKeys.columnDimensionSeparator + val.member;
1,671✔
2469
            ref.instance.parent = parent;
1,671✔
2470
            if (parentWidth) {
1,671!
2471
                ref.instance.width = isAuto ? 'auto' : isPercent ? childWidth + '%' : childWidth + 'px';
×
2472
            }
2473
            ref.instance.hidden = hidden;
1,671✔
2474
            ref.instance.sortable = this._sortableColumns;
1,671✔
2475
            ref.instance.dataType = val.dataType || this.resolveDataTypes(data[0][val.member]);
1,671✔
2476
            ref.instance.formatter = val.formatter;
1,671✔
2477
            ref.changeDetectorRef.detectChanges();
1,671✔
2478
            cols.push(ref.instance);
1,671✔
2479
        });
2480
        return cols;
833✔
2481
    }
2482

2483
    /**
2484
    * @hidden @internal
2485
    */
2486
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2487
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2488

2489
    /**
2490
     * Gets/Sets a custom template when pivot grid is empty.
2491
     *
2492
     * @example
2493
     * ```html
2494
     * <igx-pivot-grid [emptyPivotGridTemplate]="myTemplate"><igx-pivot-grid>
2495
     * ```
2496
     */
2497
    @Input()
2498
    public emptyPivotGridTemplate: TemplateRef<void>;
2499

2500
    /**
2501
    * @hidden @internal
2502
    */
2503
    public override get template(): TemplateRef<any> {
2504
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
2,152✔
2505
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
2,152✔
2506
            // no enabled values and dimensions
2507
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
55✔
2508
        }
2509
        return super.template;
2,097✔
2510
    }
2511

2512
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2513
        const dimensions = PivotUtil.flatten(this.allDimensions);
156✔
2514
        dimensions.forEach(dim => {
156✔
2515
            this.dimensionInit.emit(dim);
546✔
2516
        });
2517
        const values = pivotConfig?.values;
156✔
2518
        values?.forEach(val => {
156✔
2519
            this.valueInit.emit(val);
274✔
2520
        });
2521
    }
2522

2523
    protected rowDimensionByName(memberName: string) {
2524
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2525
    }
2526

2527
    protected calculateResizerTop() {
2528
        return this.pivotUI.showRowHeaders ?
18✔
2529
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
8!
2530
            this.theadRow.nativeElement.offsetHeight;
2531
    }
2532

2533
    protected override updateDefaultRowHeight() {
2534
        super.updateDefaultRowHeight();
193✔
2535
        if (this.hasHorizontalLayout) {
193✔
2536
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2537
            this.regroupTrigger++;
12✔
2538
        }
2539
    }
2540

2541
    /**
2542
     * @hidden @internal
2543
     */
2544
     public createRow(index: number, data?: any): RowType {
2545
        let row: RowType;
2546

2547
        const dataIndex = this._getDataViewIndex(index);
×
2548
        const rec = data ?? this.dataView[dataIndex];
×
2549

2550

2551
        if (!row && rec) {
×
2552
            row = new IgxPivotGridRow(this, index, rec);
×
2553
        }
2554
        return row;
×
2555
    }
2556
}
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