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

IgniteUI / igniteui-angular / 11741984483

08 Nov 2024 12:19PM CUT coverage: 91.57% (-0.04%) from 91.606%
11741984483

Pull #14999

github

web-flow
Merge dba70cfe6 into 7b8563221
Pull Request #14999: fix(grid): add coerceToInt attribute to IPinningConfig and pagingMode props

12947 of 15174 branches covered (85.32%)

26243 of 28659 relevant lines covered (91.57%)

33883.34 hits per line

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

89.85
/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, NgIf, NgClass, NgStyle, NgFor } 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, 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

106
let NEXT_ID = 0;
2✔
107
const MINIMUM_COLUMN_WIDTH = 200;
2✔
108
const MINIMUM_COLUMN_WIDTH_SUPER_COMPACT = 104;
2✔
109

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

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

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

230

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

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

257

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

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

284

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

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

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

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

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

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

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

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

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

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

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

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

394

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

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

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

422

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

778

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

890

891

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1008
        });
1009

1010
        return selectedRowIds;
15✔
1011
    }
1012

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

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

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

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

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

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

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

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

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

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

1167
    /** @hidden */
1168
    public override featureColumnsWidth() {
1169
        return this.pivotRowWidths;
8,549✔
1170
    }
1171

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

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

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

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

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

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

1264
    /**
1265
     * @hidden @internal
1266
     */
1267
    public rowDimensionWidthToPixels(dim: IPivotDimension): number {
1268
        if (!dim?.width) {
87,671✔
1269
            return MINIMUM_COLUMN_WIDTH;
85,030✔
1270
        }
1271
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
2,641✔
1272
        const isAuto = dim.width && dim.width.indexOf('auto') !== -1;
2,641✔
1273
        if (isPercent) {
2,641✔
1274
            return Math.round(parseFloat(dim.width) / 100 * this.calcWidth);
672✔
1275
        } else if (isAuto) {
1,969✔
1276
            return dim.autoWidth;
198✔
1277
        } else {
1278
            return parseInt(dim.width, 10);
1,771✔
1279
        }
1280
    }
1281

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

1289
    /** @hidden @internal */
1290
    public get pivotContentCalcWidth() {
1291
        const totalDimWidth = this.rowDimensions.length > 0 ?
2,115✔
1292
            this.rowDimensions.map((dim) => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur) :
2,885✔
1293
            0;
1294
        return this.calcWidth - totalDimWidth;
2,115✔
1295
    }
1296

1297
    /** @hidden @internal */
1298
    public get pivotPinnedWidth() {
1299
        return this.isPinningToStart ? this.pinnedWidth : this.headerFeaturesWidth;
10,575!
1300
    }
1301

1302
    /** @hidden @internal */
1303
    public get pivotUnpinnedWidth() {
1304
        return this.unpinnedWidth || 0;
2,115✔
1305
    }
1306

1307
    /** @hidden @internal */
1308
    public get rowDimensions() {
1309
        return this.pivotConfiguration.rows?.filter(x => x.enabled) || [];
115,592✔
1310
    }
1311

1312
    /** @hidden @internal */
1313
    public set visibleRowDimensions(value: IPivotDimension[]) {
1314
        this._visibleRowDimensions = value;
384✔
1315
    }
1316

1317
    public get visibleRowDimensions() {
1318
        return this._visibleRowDimensions || this.rowDimensions;
33,277!
1319
    }
1320

1321
    /** @hidden @internal */
1322
    public get columnDimensions() {
1323
        return this.pivotConfiguration.columns?.filter(x => x.enabled) || [];
300,000✔
1324
    }
1325

1326
    /** @hidden @internal */
1327
    public get filterDimensions() {
1328
        return this.pivotConfiguration.filters?.filter(x => x.enabled) || [];
6,101✔
1329
    }
1330

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

1336
    public toggleColumn(col: IgxColumnComponent) {
1337
        const state = this.columnGroupStates.get(col.field);
4✔
1338
        const newState = !state;
4✔
1339
        this.columnGroupStates.set(col.field, newState);
4✔
1340
        this.toggleRowGroup(col, newState);
4✔
1341
        this.reflow();
4✔
1342
    }
1343

1344
    protected override getColumnWidthSum(): number {
1345
        let colSum = super.getColumnWidthSum();
×
1346
        colSum += this.rowDimensions.map(dim => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur, 0);
×
1347
        return colSum;
×
1348
    }
1349

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1648
        super.dataRebinding(event);
353✔
1649
    }
1650

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2080
        return super.activeDescendant;
4,032✔
2081
    }
2082

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

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

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

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

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

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

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

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

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

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

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

2251
    /** @hidden @internal */
2252
    public get hasDimensionsToAutosize() {
2253
        return this.rowDimensions.some(x => x.width === 'auto' && !x.autoWidth);
684✔
2254
    }
2255

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

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

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

2329
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
20✔
2330
                        sibling.children.reset(measureChildren);
20✔
2331
                        columns = columns.concat(measureChildren);
20✔
2332
                    }
2333

2334
                } else {
2335
                    col.children.reset(filteredChildren);
1✔
2336
                    columns = columns.concat(children);
1✔
2337
                    if (value.dimension.childLevel) {
1✔
2338
                        const sibling = this.createColumnForDimension(value, data, parent, false);
1✔
2339
                        columns.push(sibling);
1✔
2340
                    }
2341
                }
2342
            }
2343
        });
2344

2345
        return columns;
285✔
2346
    }
2347

2348

2349
    protected generateConfig() {
2350
        if (!this.data) return;
1!
2351

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

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

2428
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2429
        if (dim.width) {
×
2430
            return dim.width;
×
2431
        }
2432
        return this.minColumnWidth + 'px';
×
2433
    }
2434

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

2459
    /**
2460
    * @hidden @internal
2461
    */
2462
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2463
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2464

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

2476
    /**
2477
    * @hidden @internal
2478
    */
2479
    public override get template(): TemplateRef<any> {
2480
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
2,115✔
2481
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
2,115✔
2482
            // no enabled values and dimensions
2483
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
55✔
2484
        }
2485
        return super.template;
2,060✔
2486
    }
2487

2488
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2489
        const dimensions = PivotUtil.flatten(this.allDimensions);
149✔
2490
        dimensions.forEach(dim => {
149✔
2491
            this.dimensionInit.emit(dim);
522✔
2492
        });
2493
        const values = pivotConfig?.values;
149✔
2494
        values?.forEach(val => {
149✔
2495
            this.valueInit.emit(val);
261✔
2496
        });
2497
    }
2498

2499
    protected rowDimensionByName(memberName: string) {
2500
        return this.visibleRowDimensions.find((rowDim) => rowDim.memberName === memberName);
×
2501
    }
2502

2503
    protected calculateResizerTop() {
2504
        return this.pivotUI.showRowHeaders ?
18✔
2505
            (this.theadRow.pivotFilterContainer?.nativeElement.offsetHeight || 0) + (this.theadRow.pivotRowContainer?.nativeElement.offsetHeight || 0) :
8!
2506
            this.theadRow.nativeElement.offsetHeight;
2507
    }
2508

2509
    protected override updateDefaultRowHeight() {
2510
        super.updateDefaultRowHeight();
185✔
2511
        if (this.hasHorizontalLayout) {
185✔
2512
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2513
            this.regroupTrigger++;
12✔
2514
        }
2515
    }
2516
}
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

© 2025 Coveralls, Inc