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

IgniteUI / igniteui-angular / 14189776419

01 Apr 2025 07:28AM UTC coverage: 91.548% (-0.06%) from 91.611%
14189776419

Pull #15209

github

web-flow
Merge 24eb27e29 into eb5864455
Pull Request #15209: fix(pivot-grid): added createRow method for grid based events

13357 of 15634 branches covered (85.44%)

0 of 18 new or added lines in 2 files covered. (0.0%)

3 existing lines in 2 files now uncovered.

26916 of 29401 relevant lines covered (91.55%)

34370.82 hits per line

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

89.52
/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, 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 } 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
    GridType, 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>();
130✔
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>();
130✔
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>();
130✔
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>();
130✔
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[]>();
130✔
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>();
130✔
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;
152✔
341
        this.emitInitEvents(this._pivotConfiguration);
152✔
342
        this.filteringExpressionsTree = PivotUtil.buildExpressionTree(value);
152✔
343
        if (!this._init) {
152✔
344
            this.setupColumns();
22✔
345
        }
346
        this.notifyChanges(true);
152✔
347
    }
348

349
    /* mustSetInCodePlatforms: WebComponents;Blazor */
350
    public get pivotConfiguration() {
351
        return this._pivotConfiguration || { rows: null, columns: null, values: null, filters: null };
925,347✔
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;
130✔
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;
133,278✔
385
    }
386

387
    /**
388
     * @hidden @internal
389
     */
390
    @HostBinding('attr.role')
391
    public role = 'grid';
130✔
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,004✔
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) {
113,501✔
416
            return Size.Small;
139✔
417
        }
418
        return super.gridSize;
113,362✔
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,530✔
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,613✔
483
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
1✔
484
        } else {
485
            return MINIMUM_COLUMN_WIDTH;
5,612✔
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[] = [];
130✔
512

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

709
    public set defaultExpandState(val: boolean) {
710
        this._defaultExpandState = val;
120✔
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;
130✔
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;
130✔
763

764
    /**
765
     * @hidden @internal
766
     */
767
    public override toolbarExporting = new EventEmitter<IGridToolbarExportEventArgs>();
130✔
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;
35,825✔
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 [];
146,733✔
841
    }
842

843
    /**
844
    * @hidden @internal
845
    */
846
    public override get unpinnedColumns(): IgxColumnComponent[] {
847
        return super.unpinnedColumns;
25,453✔
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;
22,957✔
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;
597✔
880
    }
881

882
    /**
883
     * @hidden @internal
884
     */
885
    public override get transactions(): TransactionService<Transaction, State> {
886
        return this._transactions;
525,890✔
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;
223,533✔
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 {};
180,712✔
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,
130✔
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(
130✔
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;
130✔
1065
        super.ngOnInit();
130✔
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([]);
130✔
1074
        Promise.resolve().then(() => {
130✔
1075
            if (this.autoGenerateConfig) {
130!
1076
                this.generateConfig();
×
1077
            }
1078
            this.setupColumns();
130✔
1079
        });
1080
        if (this.valueChipTemplateDirective) {
130!
1081
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
×
1082
        }
1083
        if (this.rowDimensionHeaderDirective) {
130!
1084
            this.rowDimensionHeaderTemplate = this.rowDimensionHeaderDirective.template;
×
1085
        }
1086
    }
1087

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

1097
    /**
1098
     * @hidden @internal
1099
     */
1100
    public ngOnChanges(changes: SimpleChanges) {
1101
        if (changes.superCompactMode && !changes.superCompactMode.isFirstChange()) {
177!
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,637✔
1128
        if (!config) return [];
1,637✔
1129
        return (config.rows || []).concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
4,043!
1130
    }
1131

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

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

1152
    protected get emptyBottomSize() {
1153
        return this.totalHeight - (<any>this.verticalScroll).scrollComponent.size;
4,761✔
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,024✔
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,280✔
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 || [];
138!
1207
        if (!this._init) {
138✔
1208
            if (this.autoGenerateConfig) {
8✔
1209
                this.generateConfig();
1✔
1210
            }
1211
            this.setupColumns();
8✔
1212
            this.reflow();
8✔
1213
        }
1214
        this.cdr.markForCheck();
138✔
1215
        if (this.height === null || this.height.indexOf('%') !== -1) {
138✔
1216
            // If the height will change based on how much data there is, recalculate sizes in igxForOf.
1217
            this.notifyChanges(true);
52✔
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,532✔
1231
    }
1232

1233
    /**
1234
     * @hidden
1235
     */
1236
    public getContext(rowData, rowIndex): any {
1237
        return {
10,815✔
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,037✔
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;
42,916✔
1260
        if (isAuto) {
42,916✔
1261
            return dim.autoWidth ? dim.autoWidth + 'px' : 'fit-content';
121!
1262
        } else {
1263
            return this.rowDimensionWidthToPixels(dim) + 'px';
42,795✔
1264
        }
1265
    }
1266

1267
    /**
1268
     * @hidden @internal
1269
     */
1270
    public rowDimensionWidthToPixels(dim: IPivotDimension): number {
1271
        if (!dim?.width) {
90,712✔
1272
            return MINIMUM_COLUMN_WIDTH;
88,077✔
1273
        }
1274
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
2,635✔
1275
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
2,635✔
1276
        if (isPercent) {
2,635✔
1277
            return Math.round(parseFloat(dim.width) / 100 * this.calcWidth);
695✔
1278
        } else if (isAuto) {
1,940✔
1279
            return dim.autoWidth;
108✔
1280
        } else {
1281
            return parseInt(dim.width, 10);
1,832✔
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.visibleRowDimensions.length) {
2,138✔
1295
            return Math.max(0, this.calcWidth - this.pivotRowWidths);
219✔
1296
        }
1297

1298
        const totalDimWidth = this.visibleRowDimensions.length > 0 ?
1,919!
1299
            this.visibleRowDimensions.map((dim) => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur) :
3,001✔
1300
            0;
1301
        return this.calcWidth - totalDimWidth;
1,919✔
1302
    }
1303

1304
    /** @hidden @internal */
1305
    public get pivotPinnedWidth() {
1306
        return !this._init ? (this.isPinningToStart ? this.pinnedWidth : this.headerFeaturesWidth) : 0;
10,690!
1307
    }
1308

1309
    /** @hidden @internal */
1310
    public get pivotUnpinnedWidth() {
1311
        return this.unpinnedWidth || 0;
2,138!
1312
    }
1313

1314
    /** @hidden @internal */
1315
    public get rowDimensions() {
1316
        return this.pivotConfiguration.rows?.filter(x => x.enabled) || [];
111,031✔
1317
    }
1318

1319
    /** @hidden @internal */
1320
    public set visibleRowDimensions(value: IPivotDimension[]) {
1321
        this._visibleRowDimensions = value;
387✔
1322
    }
1323

1324
    public get visibleRowDimensions() {
1325
        return this._visibleRowDimensions || this.rowDimensions;
38,432!
1326
    }
1327

1328
    /** @hidden @internal */
1329
    public get columnDimensions() {
1330
        return this.pivotConfiguration.columns?.filter(x => x.enabled) || [];
304,746✔
1331
    }
1332

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

1338
    /** @hidden @internal */
1339
    public get values() {
1340
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
673,331✔
1341
    }
1342

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

1351
    /**
1352
     * @hidden @internal
1353
     */
1354
    public override isRecordPinnedByIndex(_rowIndex: number) {
1355
        return null;
×
1356
    }
1357

1358
    /**
1359
     * @hidden @internal
1360
     */
1361
    public override toggleColumnVisibility(_args: IColumnVisibilityChangedEventArgs) {
1362
        return;
×
1363
    }
1364

1365
    /**
1366
     * @hidden @internal
1367
     */
1368
    public override expandAll() {
1369
    }
1370

1371
    /**
1372
     * @hidden @internal
1373
     */
1374
    public override collapseAll() {
1375
    }
1376

1377
    /**
1378
     * @hidden @internal
1379
     */
1380
    public override expandRow(_rowID: any) {
1381
    }
1382

1383
    /**
1384
     * @hidden @internal
1385
     */
1386
    public override collapseRow(_rowID: any) {
1387
    }
1388

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

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

1404
    public override set totalRecords(_total: number) {
1405
    }
1406

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

1413
    /**
1414
     * @hidden @internal
1415
     */
1416
    public override addRow(_data: any): void {
1417
    }
1418

1419
    /**
1420
     * @hidden @internal
1421
     */
1422
    public override deleteRow(_rowSelector: any): any {
1423
    }
1424

1425
    /**
1426
     * @hidden @internal
1427
     */
1428
    public override updateCell(_value: any, _rowSelector: any, _column: string): void {
1429
    }
1430

1431
    /**
1432
     * @hidden @internal
1433
     */
1434
    public override updateRow(_value: any, _rowSelector: any): void {
1435
    }
1436

1437
    /**
1438
     * @hidden @internal
1439
     */
1440
    public override enableSummaries(..._rest) {
1441
    }
1442

1443
    /**
1444
     * @hidden @internal
1445
     */
1446
    public override disableSummaries(..._rest) {
1447
    }
1448

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

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

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

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

1477
    /**
1478
     * @hidden @internal
1479
     */
1480
    public override get pinnedRowHeight() {
1481
        return;
2,735✔
1482
    }
1483

1484
    /**
1485
     * @hidden @internal
1486
     */
1487
    public override get hasEditableColumns(): boolean {
1488
        return;
×
1489
    }
1490

1491
    /**
1492
     * @hidden @internal
1493
     */
1494
    public override get hasSummarizedColumns(): boolean {
1495
        return;
5✔
1496
    }
1497

1498
    /**
1499
     * @hidden @internal
1500
     */
1501
    public override get hasMovableColumns(): boolean {
1502
        return;
37,990✔
1503
    }
1504

1505
    /**
1506
     * @hidden @internal
1507
     */
1508
    public override get pinnedDataView(): any[] {
1509
        return [];
10,815✔
1510
    }
1511

1512
    /**
1513
     * @hidden @internal
1514
     */
1515
    public override openAdvancedFilteringDialog(_overlaySettings?: OverlaySettings) {
1516
    }
1517

1518
    /**
1519
     * @hidden @internal
1520
     */
1521
    public override closeAdvancedFilteringDialog(_applyChanges: boolean) {
1522
    }
1523

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

1531
    /**
1532
     * @hidden @internal
1533
     */
1534
    public override beginAddRowById(_rowID: any, _asChild?: boolean): void {
1535
    }
1536

1537
    /**
1538
     * @hidden @internal
1539
     */
1540
    public override beginAddRowByIndex(_index: number): void {
1541
    }
1542

1543
    /**
1544
     * @hidden @internal
1545
     */
1546
    public override clearSearch() { }
1547

1548
    /**
1549
    * @hidden @internal
1550
    */
1551
    public override refreshSearch(_updateActiveInfo?: boolean, _endEdit = true): number {
95✔
1552
        return 0;
482✔
1553
    }
1554

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

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

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

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

1585
    /**
1586
    * @hidden @internal
1587
    */
1588
    public override getPinnedWidth(takeHidden = false) {
589✔
1589
        return super.getPinnedWidth(takeHidden);
2,408✔
1590
    }
1591

1592
    /**
1593
     * @hidden @internal
1594
     */
1595
    public override get totalHeight() {
1596
        return this.calcHeight;
9,681✔
1597
    }
1598

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

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

1634
    /**
1635
    * @hidden @internal
1636
    */
1637
    public override setupColumns() {
1638
        super.setupColumns();
245✔
1639
    }
1640

1641
    /**
1642
    * @hidden @internal
1643
    */
1644
    public override dataRebinding(event: IForOfDataChangingEventArgs) {
1645
        if (this.hasHorizontalLayout) {
356✔
1646
            this.dimensionDataColumns = this.generateDimensionColumns();
30✔
1647
        }
1648

1649
        super.dataRebinding(event);
356✔
1650
    }
1651

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

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

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

1735
        if (prevCollectionType === PivotDimensionType.Column) {
8✔
1736
            this.setupColumns();
3✔
1737
        }
1738
    }
1739

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2039
    /** @hidden @internal */
2040
    public get hasHorizontalLayout() {
2041
        return this.pivotUI.rowLayout === PivotRowLayoutType.Horizontal;
100,422✔
2042
    }
2043

2044
    /**
2045
    * @hidden
2046
    */
2047
    public get hasMultipleValues() {
2048
        return this.values.length > 1;
171,601✔
2049
    }
2050

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

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

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

2078
            return `${this.id}_${activeElem.row}_${activeElem.column}`;
198✔
2079
        }
2080

2081
        return super.activeDescendant;
4,078✔
2082
    }
2083

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

2110
    protected override buildDataView(data: any[]) {
2111
        this._dataView = data;
387✔
2112
    }
2113

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

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

2130
    protected override verticalScrollHandler(event) {
2131
        this.verticalRowDimScrollContainers.forEach(x => {
×
2132
            x.onScroll(event);
×
2133
        });
2134
        super.verticalScrollHandler(event);
×
2135
    }
2136

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

2183
        this.updateColumns(columns);
243✔
2184
        this.pipeTrigger++;
243✔
2185
        this.reflow();
243✔
2186
    }
2187

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

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

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

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

2251
        if (this.isColumnWidthSum) {
1!
2252
            this.calcWidth = this.getColumnWidthSum();
×
2253
        }
2254
    }
2255

2256
    /** @hidden @internal */
2257
    public get hasDimensionsToAutosize() {
2258
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
685✔
2259
    }
2260

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

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

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

2334
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2335
                        sibling.children.reset(measureChildren);
20✔
2336
                        columns = columns.concat(measureChildren);
20✔
2337
                    }
2338

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

2350
        return columns;
288✔
2351
    }
2352

2353

2354
    protected generateConfig() {
2355
        if (!this.data) return;
1!
2356

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

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

2433
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2434
        if (dim.width) {
×
2435
            return dim.width;
×
2436
        }
2437
        return this.minColumnWidth + 'px';
×
2438
    }
2439

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

2464
    /**
2465
    * @hidden @internal
2466
    */
2467
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2468
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2469

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

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

2493
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2494
        const dimensions = PivotUtil.flatten(this.allDimensions);
152✔
2495
        dimensions.forEach(dim => {
152✔
2496
            this.dimensionInit.emit(dim);
531✔
2497
        });
2498
        const values = pivotConfig?.values;
152✔
2499
        values?.forEach(val => {
152✔
2500
            this.valueInit.emit(val);
267✔
2501
        });
2502
    }
2503

2504
    protected rowDimensionByName(memberName: string) {
2505
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2506
    }
2507

2508
    protected calculateResizerTop() {
2509
        return this.pivotUI.showRowHeaders ?
18✔
2510
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
8!
2511
            this.theadRow.nativeElement.offsetHeight;
2512
    }
2513

2514
    protected override updateDefaultRowHeight() {
2515
        super.updateDefaultRowHeight();
190✔
2516
        if (this.hasHorizontalLayout) {
190✔
2517
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2518
            this.regroupTrigger++;
12✔
2519
        }
2520
    }
2521

2522
    /**
2523
     * @hidden @internal
2524
     */
2525
     public createRow(index: number, data?: any): RowType {
2526
        let row: RowType;
2527

NEW
2528
        const dataIndex = this._getDataViewIndex(index);
×
NEW
2529
        const rec = data ?? this.dataView[dataIndex];
×
2530

2531

NEW
2532
        if (!row && rec) {
×
NEW
2533
            row = new IgxPivotGridRow(this, index, rec);
×
2534
        }
NEW
2535
        return row;
×
2536
    }
2537
}
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