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

IgniteUI / igniteui-angular / 13679189163

05 Mar 2025 03:13PM CUT coverage: 91.647% (+0.002%) from 91.645%
13679189163

Pull #15376

github

web-flow
Merge 4e8f64a84 into eda67f4e5
Pull Request #15376: feat(pivotGrid): Improve PivotGrid visually when there's no data or has empty area at the bottom.

13334 of 15604 branches covered (85.45%)

4 of 4 new or added lines in 2 files covered. (100.0%)

60 existing lines in 2 files now uncovered.

26893 of 29344 relevant lines covered (91.65%)

33698.11 hits per line

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

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

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

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_SERVICE_BASE, useClass: GridBaseAPIService },
155
        { provide: IGX_GRID_BASE, useExisting: IgxPivotGridComponent },
156
        { provide: IgxFilteringService, useClass: IgxPivotFilteringService },
157
        IgxPivotGridNavigationService,
158
        IgxPivotColumnResizingService,
159
        IgxForOfSyncService,
160
        IgxForOfScrollSyncService
161
    ],
162
    imports: [
163
        NgClass,
164
        NgStyle,
165
        NgTemplateOutlet,
166
        IgxPivotHeaderRowComponent,
167
        IgxGridBodyDirective,
168
        IgxGridDragSelectDirective,
169
        IgxColumnMovingDropDirective,
170
        IgxGridForOfDirective,
171
        IgxTemplateOutletDirective,
172
        IgxPivotRowComponent,
173
        IgxToggleDirective,
174
        IgxCircularProgressBarComponent,
175
        IgxSnackbarComponent,
176
        IgxOverlayOutletDirective,
177
        IgxPivotGridColumnResizerComponent,
178
        IgxIconComponent,
179
        IgxPivotRowDimensionContentComponent,
180
        IgxGridExcelStyleFilteringComponent,
181
        IgxExcelStyleColumnOperationsTemplateDirective,
182
        IgxExcelStyleFilterOperationsTemplateDirective,
183
        IgxExcelStyleSearchComponent,
184
        IgxGridRowClassesPipe,
185
        IgxGridRowStylesPipe,
186
        IgxPivotRowPipe,
187
        IgxPivotRowExpansionPipe,
188
        IgxPivotAutoTransform,
189
        IgxPivotColumnPipe,
190
        IgxPivotGridFilterPipe,
191
        IgxPivotGridSortingPipe,
192
        IgxPivotGridColumnSortingPipe,
193
        IgxPivotCellMergingPipe,
194
        IgxPivotGridHorizontalRowGrouping,
195
        IgxPivotRowDimensionMrlRowComponent
196
    ],
197
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
198
})
199
export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnInit, AfterContentInit,
2✔
200
    GridType, AfterViewInit, OnChanges {
201

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

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

228

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

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

255

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

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

282

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

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

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

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

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

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

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

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

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

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

382
    public get pivotUI() {
383
        return this._pivotUI;
132,853✔
384
    }
385

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

392

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

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

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

420

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

669
    /**
670
     * @hidden @internal
671
     */
672
    public rowDimensionResizing = true;
129✔
673

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

776

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

888

889

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1006
        });
1007

1008
        return selectedRowIds;
15✔
1009
    }
1010

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

1058
    public override navigation: IgxPivotGridNavigationService;
1059

1060
    /**
1061
     * @hidden
1062
     */
1063
    public override ngOnInit() {
1064
        // pivot grid always generates columns automatically.
1065
        this.autoGenerate = true;
129✔
1066
        super.ngOnInit();
129✔
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([]);
129✔
1075
        Promise.resolve().then(() => {
129✔
1076
            if (this.autoGenerateConfig) {
129!
UNCOV
1077
                this.generateConfig();
×
1078
            }
1079
            this.setupColumns();
129✔
1080
        });
1081
        if (this.valueChipTemplateDirective) {
129!
UNCOV
1082
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
×
1083
        }
1084
        if (this.rowDimensionHeaderDirective) {
129!
UNCOV
1085
            this.rowDimensionHeaderTemplate = this.rowDimensionHeaderDirective.template;
×
1086
        }
1087
    }
1088

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

1098
    /**
1099
     * @hidden @internal
1100
     */
1101
    public ngOnChanges(changes: SimpleChanges) {
1102
        if (changes.superCompactMode && !changes.superCompactMode.isFirstChange()) {
176!
1103
            this._shouldUpdateSizes = true;
×
UNCOV
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,629✔
1129
        if (!config) return [];
1,629✔
1130
        return (config.rows || []).concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
4,027!
1131
    }
1132

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

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

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

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

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

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

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

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

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

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

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

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

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

1293
    /** @hidden @internal */
1294
    public get pivotContentCalcWidth() {
1295
        if (!this.visibleRowDimensions.length) {
2,127✔
1296
            return Math.max(0, this.calcWidth - this.pivotRowWidths);
218✔
1297
        }
1298

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1650
        super.dataRebinding(event);
355✔
1651
    }
1652

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2082
        return super.activeDescendant;
4,056✔
2083
    }
2084

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2351
        return columns;
287✔
2352
    }
2353

2354

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

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

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

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

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

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

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

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

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

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

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

2515
    protected override updateDefaultRowHeight() {
2516
        super.updateDefaultRowHeight();
188✔
2517
        if (this.hasHorizontalLayout) {
188✔
2518
            // Trigger pipes to recalc heights for the horizontal layout mrl rows.
2519
            this.regroupTrigger++;
12✔
2520
        }
2521
    }
2522
}
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