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

IgniteUI / igniteui-angular / 6146764501

11 Sep 2023 01:01PM CUT coverage: 92.263%. Remained the same
6146764501

push

github

web-flow
Merge pull request #13437 from IgniteUI/thristodorova/fix-13433-16.0.x

fix(grid): add return type and return value to endEdit method

15311 of 17991 branches covered (0.0%)

1 of 1 new or added line in 1 file covered. (100.0%)

26844 of 29095 relevant lines covered (92.26%)

29497.61 hits per line

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

91.07
/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
    ApplicationRef,
25
    ContentChild,
26
    createComponent,
27
    EnvironmentInjector,
28
    CUSTOM_ELEMENTS_SCHEMA
29
} from '@angular/core';
30
import { DOCUMENT, NgTemplateOutlet, NgIf, NgClass, NgStyle, NgFor } from '@angular/common';
31

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

121✔
93
let NEXT_ID = 0;
94
const MINIMUM_COLUMN_WIDTH = 200;
95
const MINIMUM_COLUMN_WIDTH_SUPER_COMPACT = 104;
700,638✔
96

97
/**
98
 * Pivot Grid provides a way to present and manipulate data in a pivot table view.
300,612✔
99
 *
100
 * @igxModule IgxPivotGridModule
101
 * @igxGroup Grids & Lists
2✔
102
 * @igxKeywords pivot, grid, table
103
 * @igxTheme igx-grid-theme
2✔
104
 * @remarks
2✔
105
 * The Ignite UI Pivot Grid is used for grouping and aggregating simple flat data into a pivot table.  Once data
106
 * has been bound and the dimensions and values configured it can be manipulated via sorting and filtering.
107
 * @example
108
 * ```html
202,563✔
109
 * <igx-pivot-grid [data]="data" [pivotConfiguration]="configuration">
323✔
110
 * </igx-pivot-grid>
111
 * ```
202,240✔
112
 */
113
@Component({
114
    changeDetection: ChangeDetectionStrategy.OnPush,
115
    preserveWhitespaces: false,
116
    selector: 'igx-pivot-grid',
117
    templateUrl: 'pivot-grid.component.html',
2✔
118
    providers: [
2✔
119
        IgxGridCRUDService,
2!
120
        IgxGridValidationService,
2✔
121
        IgxGridSummaryService,
122
        IgxGridSelectionService,
123
        IgxColumnResizingService,
124
        GridBaseAPIService,
2✔
125
        { provide: IGX_GRID_BASE, useExisting: IgxPivotGridComponent },
126
        { provide: IgxFilteringService, useClass: IgxPivotFilteringService },
127
        IgxPivotGridNavigationService,
128
        IgxPivotColumnResizingService,
3,304✔
129
        IgxForOfSyncService,
130
        IgxForOfScrollSyncService
131
    ],
×
132
    standalone: true,
×
133
    imports: [
134
        NgIf,
135
        NgFor,
136
        NgClass,
137
        NgStyle,
138
        NgTemplateOutlet,
139
        IgxPivotHeaderRowComponent,
4,790✔
140
        IgxGridBodyDirective,
1✔
141
        IgxGridDragSelectDirective,
142
        IgxColumnMovingDropDirective,
143
        IgxGridForOfDirective,
4,789✔
144
        IgxTemplateOutletDirective,
145
        IgxPivotRowComponent,
146
        IgxToggleDirective,
147
        IgxCircularProgressBarComponent,
148
        IgxSnackbarComponent,
119,087✔
149
        IgxOverlayOutletDirective,
150
        IgxPivotGridColumnResizerComponent,
151
        IgxIconComponent,
152
        IgxPivotRowDimensionContentComponent,
153
        IgxGridExcelStyleFilteringComponent,
154
        IgxExcelStyleColumnOperationsTemplateDirective,
4,456✔
155
        IgxExcelStyleFilterOperationsTemplateDirective,
156
        IgxExcelStyleSearchComponent,
157
        IgxGridRowClassesPipe,
158
        IgxGridRowStylesPipe,
159
        IgxPivotRowPipe,
160
        IgxPivotRowExpansionPipe,
407✔
161
        IgxPivotAutoTransform,
162
        IgxPivotColumnPipe,
163
        IgxPivotGridFilterPipe,
1,544✔
164
        IgxPivotGridSortingPipe,
165
        IgxPivotGridColumnSortingPipe,
166
        IgxPivotCellMergingPipe
95✔
167
    ],
168
    schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
169
})
×
170
export class IgxPivotGridComponent extends IgxGridBaseDirective implements OnInit, AfterContentInit,
171
    GridType, AfterViewInit {
172

173
    /**
174
     * Emitted when the dimension collection is changed via the grid chip area.
×
175
     *
176
     * @remarks
177
     * Returns the new dimension collection and its type:
178
     * @example
179
     * ```html
×
180
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
181
     *              (dimensionsChange)="dimensionsChange($event)"></igx-grid>
182
     * ```
183
     */
184
    @Output()
×
185
    public dimensionsChange = new EventEmitter<IDimensionsChange>();
186

187
    /**
188
     * Emitted when any of the pivotConfiguration properties is changed via the grid chip area.
189
     *
×
190
     * @example
191
     * ```html
192
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
193
     *              (pivotConfigurationChanged)="configurationChanged($event)"></igx-grid>
194
     * ```
36,063✔
195
     */
196
    @Output()
197
    public pivotConfigurationChange = new EventEmitter<IPivotConfigurationChangedEventArgs>();
198

199

×
200
    /**
201
     * Emitted when the dimension is initialized.
202
     * @remarks
203
     * Emits the dimension that is about to be initialized.
204
     * @example
×
205
     * ```html
206
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
207
     *              (dimensionInit)="dimensionInit($event)"></igx-pivot-grid>
208
     * ```
209
     */
210
    @Output()
211
    public dimensionInit = new EventEmitter<IPivotDimension>();
212

106,685✔
213
    /**
214
     * Emitted when the value is initialized.
215
     * @remarks
216
     * Emits the value that is about to be initialized.
217
     * @example
218
     * ```html
20,891✔
219
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
220
     *              (valueInit)="valueInit($event)"></igx-pivot-grid>
221
     * ```
222
     */
223
    @Output()
224
    public valueInit = new EventEmitter<IPivotValue>();
×
225

226

227
    /**
228
     * Emitted when a dimension is sorted.
229
     *
230
     * @example
17,744✔
231
     * ```html
232
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
233
     *              (dimensionsSortingExpressionsChange)="dimensionsSortingExpressionsChange($event)"></igx-pivot-grid>
234
     * ```
235
     */
236
    @Output()
6,145✔
237
    public dimensionsSortingExpressionsChange = new EventEmitter<ISortingExpression[]>();
238

239
    /**
240
     * Emitted when the values collection is changed via the grid chip area.
241
     *
381✔
242
     * @remarks
243
     * Returns the new dimension
244
     * @example
245
     * ```html
246
     * <igx-pivot-grid #grid [data]="localData" [height]="'305px'"
247
     *              (valuesChange)="valuesChange($event)"></igx-grid>
385,673✔
248
     * ```
249
    */
250
    @Output()
251
    public valuesChange = new EventEmitter<IValuesChange>();
252

253

×
254
    /**
255
     * Gets the sorting expressions generated for the dimensions.
256
     *
257
     * @example
258
     * ```typescript
163,905✔
259
     * const expressions = this.grid.dimensionsSortingExpressions;
260
     * ```
261
     */
262
    public get dimensionsSortingExpressions() {
263
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
135,336✔
264
        const dimensionsSortingExpressions = PivotSortUtil.generateDimensionSortingExpressions(allEnabledDimensions);
265
        return dimensionsSortingExpressions;
266
    }
267

268
    /** @hidden @internal */
×
269
    @ViewChild(IgxPivotHeaderRowComponent, { static: true })
270
    public override theadRow: IgxPivotHeaderRowComponent;
271

272
    /**
273
    * @hidden @internal
×
274
    */
275
    @ContentChild(IgxPivotValueChipTemplateDirective, { read: IgxPivotValueChipTemplateDirective })
276
    protected valueChipTemplateDirective: IgxPivotValueChipTemplateDirective;
277

278
    /**
×
279
     * Gets/Sets a custom template for the value chips.
280
     *
281
     * @example
282
     * ```html
283
     * <igx-pivot-grid [valueChipTemplate]="myTemplate"><igx-pivot-grid>
284
     * ```
285
     */
286
     @Input()
×
287
     public valueChipTemplate: TemplateRef<IgxPivotGridValueTemplateContext>;
288

289
    @Input()
290
    /**
291
     * Gets/Sets the pivot configuration with all related dimensions and values.
292
     *
×
293
     * @example
294
     * ```html
295
     * <igx-pivot-grid [pivotConfiguration]="config"></igx-pivot-grid>
×
296
     * ```
297
     */
298
    public set pivotConfiguration(value: IPivotConfiguration) {
299
        this._pivotConfiguration = value;
300
        this.emitInitEvents(this._pivotConfiguration);
12✔
301
        this.filteringExpressionsTree = PivotUtil.buildExpressionTree(value);
3✔
302
        if (!this._init) {
303
            this.setupColumns();
9✔
304
        }
9✔
305
        this.notifyChanges(true);
140✔
306
    }
140✔
307

261✔
308
    public get pivotConfiguration() {
261✔
309
        return this._pivotConfiguration || { rows: null, columns: null, values: null, filters: null };
261✔
310
    }
483✔
311

483✔
312
    @Input()
23✔
313
    /**
23✔
314
     * Gets/Sets the pivot configuration ui for the pivot grid - chips and their
23✔
315
     * corresponding containers for row, filter, column dimensions and values
316
     *
460✔
317
     * @example
318
     * ```html
261✔
319
     * <igx-pivot-grid [showPivotConfigurationUI]="false"></igx-pivot-grid>
261✔
320
     * ```
23✔
321
     */
322
    public showPivotConfigurationUI = true;
323

324
    /**
9✔
325
     * @hidden @internal
326
     */
327
    @HostBinding('attr.role')
328
    public role = 'grid';
329

330

331
    /**
332
     * Enables a super compact theme for the component.
333
     * @remarks
334
     * Overrides the displayDensity option if one is set.
335
     * @example
91,847✔
336
     * ```html
316✔
337
     * <igx-pivot-grid [superCompactMode]="true"></igx-pivot-grid>
338
     * ```
91,531✔
339
     */
340
    @HostBinding('class.igx-grid__pivot--super-compact')
341
    @Input()
105✔
342
    public get superCompactMode() {
105✔
343
        return this._superCompactMode;
105✔
344
    }
105✔
345

105✔
346
    public set superCompactMode(value) {
105✔
347
        Promise.resolve().then(() => {
105✔
348
            // wait for the current detection cycle to end before triggering a new one.
105✔
349
            this._superCompactMode = value;
105✔
350
            this.cdr.detectChanges();
105✔
351
        });
105✔
352
    }
105✔
353

105✔
354
    /**
105✔
355
    * Returns the theme of the component.
105✔
356
    * The default theme is `comfortable`.
105✔
357
    * Available options are `comfortable`, `cosy`, `compact`.
105✔
358
    * @remarks
105✔
359
    * If set while superCompactMode is enabled will have no affect.
105✔
360
    * ```typescript
105✔
361
    * let componentTheme = this.component.displayDensity;
105✔
362
    * ```
105✔
363
    */
105✔
364
    @Input()
105✔
365
    public override get displayDensity(): DisplayDensity {
105✔
366
        if (this.superCompactMode) {
105✔
367
            return DisplayDensity.compact;
105✔
368
        }
105✔
369
        return super.displayDensity;
105✔
370
    }
105✔
371

105✔
372
    /**
105✔
373
    * Sets the theme of the component.
374
    */
105✔
375
    public override set displayDensity(val: DisplayDensity) {
376
        const currentDisplayDensity = this._displayDensity;
105✔
377
        this._displayDensity = val as DisplayDensity;
378

379
        if (currentDisplayDensity !== this._displayDensity) {
380
            const densityChangedArgs: IDensityChangedEventArgs = {
105✔
381
                oldDensity: currentDisplayDensity,
382
                newDensity: this._displayDensity
383
            };
384

105✔
385
            this.densityChanged.emit(densityChangedArgs);
105✔
386
        }
105✔
387
    }
105✔
388

105✔
389
    /**
105✔
390
     * Gets/Sets the values clone strategy of the pivot grid when assigning them to different dimensions.
105✔
391
     *
105✔
392
     * @example
393
     * ```html
394
     *  <igx-pivot-grid #grid [data]="localData" [pivotValueCloneStrategy]="customCloneStrategy"></igx-pivot-grid>
395
     * ```
105✔
396
     * @hidden @internal
397
     */
398
    @Input()
399
    public get pivotValueCloneStrategy(): IDataCloneStrategy {
105✔
400
        return this._pivotValueCloneStrategy;
401
    }
402

403
    public set pivotValueCloneStrategy(strategy: IDataCloneStrategy) {
105✔
404
        if (strategy) {
405
            this._pivotValueCloneStrategy = strategy;
406
        }
407
    }
408

409
    /**
410
     * @hidden @internal
105✔
411
     */
105✔
412
    @ViewChild('record_template', { read: TemplateRef, static: true })
413
    public recordTemplate: TemplateRef<any>;
414

415
    /**
416
     * @hidden @internal
417
     */
418
    @ViewChild('headerTemplate', { read: TemplateRef, static: true })
105✔
419
    public headerTemplate: TemplateRef<any>;
105✔
420

105✔
421
    /**
422
     * @hidden @internal
105!
423
     */
×
424
    @ViewChild(IgxPivotGridColumnResizerComponent)
425
    public override resizeLine: IgxPivotGridColumnResizerComponent;
426

427
    /**
428
     * @hidden @internal
429
     */
430
    @ViewChildren(IgxGridExcelStyleFilteringComponent, { read: IgxGridExcelStyleFilteringComponent })
105✔
431
    public override excelStyleFilteringComponents: QueryList<IgxGridExcelStyleFilteringComponent>;
105✔
432

433
    /**
434
     * @hidden @internal
435
     */
436
    @ViewChildren(IgxPivotRowDimensionContentComponent)
437
    protected rowDimensionContentCollection: QueryList<IgxPivotRowDimensionContentComponent>;
×
438

19!
439
    /**
19✔
440
     * @hidden @internal
441
     */
19✔
442
    protected override get minColumnWidth() {
19✔
443
        if (this.superCompactMode) {
444
            return MINIMUM_COLUMN_WIDTH_SUPER_COMPACT;
445
        } else {
446
            return MINIMUM_COLUMN_WIDTH;
447
        }
448
    }
449

450
    /**
451
     * @hidden @internal
452
     */
453
    @ViewChildren('verticalRowDimScrollContainer', { read: IgxGridForOfDirective })
1,545✔
454
    public verticalRowDimScrollContainers: QueryList<IgxGridForOfDirective<any, any[]>>;
1,545✔
455

8✔
456
    /**
3,812!
457
     * @hidden @internal
458
     */
459
    @Input()
460
    public override addRowEmptyTemplate: TemplateRef<void>;
5✔
461

5!
462
    /**
5✔
463
     * @hidden @internal
5✔
464
     */
3✔
465
    @Input()
3✔
466
    public override autoGenerateExclude: string[] = [];
3✔
467

468
    /**
2✔
469
     * @hidden @internal
470
     */
471
    @Input()
472
    public override snackbarDisplayTime = 6000;
473

7,203✔
474
    /**
475
     * @hidden @internal
476
     */
63,916✔
477
    @Output()
478
    public override cellEdit = new EventEmitter<IGridEditEventArgs>();
479

×
480
    /**
481
     * @hidden @internal
482
     */
109!
483
    @Output()
109✔
484
    public override cellEditDone = new EventEmitter<IGridEditDoneEventArgs>();
4✔
485

4✔
486
    /**
487
     * @hidden @internal
109✔
488
     */
109✔
489
    @Output()
490
    public override cellEditEnter = new EventEmitter<IGridEditEventArgs>();
36✔
491

492
    /**
493
     * @hidden @internal
494
     */
495
    @Output()
496
    public override cellEditExit = new EventEmitter<IGridEditDoneEventArgs>();
497

498
    /**
499
     * @hidden @internal
500
     */
6,624✔
501
    @Output()
502
    public override columnMovingStart = new EventEmitter<IColumnMovingStartEventArgs>();
503

504
    /**
505
     * @hidden @internal
506
     */
8,023✔
507
    @Output()
508
    public override columnMoving = new EventEmitter<IColumnMovingEventArgs>();
509

510
    /**
511
     * @hidden @internal
512
     */
513
    @Output()
514
    public override columnMovingEnd = new EventEmitter<IColumnMovingEndEventArgs>();
515

516
    /**
517
     * @hidden @internal
518
     */
519
    @Output()
17,036✔
520
    public override columnPin = new EventEmitter<IPinColumnCancellableEventArgs>();
521

522
    /**
523
     * @hidden @internal
524
     */
525
    @Output()
56,276✔
526
    public override columnPinned = new EventEmitter<IPinColumnEventArgs>();
56,276✔
527

11,292✔
528
    /**
529
     * @hidden @internal
44,984✔
530
     */
43,298✔
531
    @Output()
532
    public override rowAdd = new EventEmitter<IGridEditEventArgs>();
1,686✔
533

1,686✔
534
    /**
478✔
535
     * @hidden @internal
536
     */
537
    @Output()
1,208✔
538
    public override rowAdded = new EventEmitter<IRowDataEventArgs>();
539

540
    /**
541
     * @hidden @internal
542
     */
543
    @Output()
544
    public override rowDeleted = new EventEmitter<IRowDataEventArgs>();
1✔
545

546
    /**
547
     * @hidden @internal
548
     */
1,544✔
549
    @Output()
2,172✔
550
    public override rowDelete = new EventEmitter<IGridEditEventArgs>();
551

1,544✔
552
    /**
553
     * @hidden @internal
554
     */
555
    @Output()
7,720!
556
    public override rowDragStart = new EventEmitter<IRowDragStartEventArgs>();
557

558
    /**
559
     * @hidden @internal
1,544✔
560
     */
561
    @Output()
562
    public override rowDragEnd = new EventEmitter<IRowDragEndEventArgs>();
563

131,450✔
564
    /**
565
     * @hidden @internal
566
     */
567
    @Output()
223,744✔
568
    public override rowEditEnter = new EventEmitter<IGridEditEventArgs>();
569

570
    /**
571
     * @hidden @internal
4,757✔
572
     */
573
    @Output()
574
    public override rowEdit = new EventEmitter<IGridEditEventArgs>();
575

494,719✔
576
    /**
577
     * @hidden @internal
578
     */
4✔
579
    @Output()
4✔
580
    public override rowEditDone = new EventEmitter<IGridEditDoneEventArgs>();
4✔
581

4✔
582
    /**
4✔
583
     * @hidden @internal
584
     */
585
    @Output()
×
586
    public override rowEditExit = new EventEmitter<IGridEditDoneEventArgs>();
×
587

×
588
    /**
589
     * @hidden @internal
590
     */
591
    @Output()
592
    public override rowPinning = new EventEmitter<IPinRowEventArgs>();
593

×
594
    /**
595
     * @hidden @internal
596
     */
597
    @Output()
598
    public override rowPinned = new EventEmitter<IPinRowEventArgs>();
599

×
600
    /** @hidden @internal */
601
    public columnGroupStates = new Map<string, boolean>();
602
    /** @hidden @internal */
603
    public dimensionDataColumns;
604
    /** @hidden @internal */
605
    public get pivotKeys() {
606
        return this.pivotConfiguration.pivotKeys || DEFAULT_PIVOT_KEYS;
607
    }
608
    /** @hidden @internal */
609
    public override isPivot = true;
610

611
    /**
612
     * @hidden @internal
613
     */
614
    public override dragRowID = null;
615

616
    /**
617
    * @hidden @internal
618
    */
619
    public override get rootSummariesEnabled(): boolean {
620
        return false;
621
    }
622

623
    /**
624
     * @hidden @internal
625
     */
2✔
626
    public rowDimensionResizing = true;
627

628
    private _emptyRowDimension: IPivotDimension = { memberName: '', enabled: true, level: 0 };
×
629
    /**
630
     * @hidden @internal
631
     */
632
    public get emptyRowDimension(): IPivotDimension {
633
        return this._emptyRowDimension;
634
    }
635

×
636
    protected _pivotValueCloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy();
637
    protected override _defaultExpandState = false;
638
    protected override _filterStrategy: IFilteringStrategy = new DimensionValuesFilteringStrategy();
639
    private _data;
640
    private _pivotConfiguration: IPivotConfiguration = { rows: null, columns: null, values: null, filters: null };
641
    private p_id = `igx-pivot-grid-${NEXT_ID++}`;
642
    private _superCompactMode = false;
643

644
    /**
645
    * Gets/Sets the default expand state for all rows.
646
    */
647
    @Input()
648
    public get defaultExpandState() {
649
        return this._defaultExpandState;
650
    }
651

652
    public set defaultExpandState(val: boolean) {
653
        this._defaultExpandState = val;
654
    }
655

656
    /**
657
     * @hidden @internal
658
     */
659
    @Input()
660
    public override get pagingMode() {
661
        return;
662
    }
663

664
    public override set pagingMode(_val: GridPagingMode) {
665
    }
666

667
    /**
668
     * @hidden @internal
669
     */
670
    @WatchChanges()
671
    @Input()
×
672
    public override get hideRowSelectors() {
673
        return;
674
    }
675

676
    public override set hideRowSelectors(_value: boolean) {
677
    }
×
678

679
    /**
680
     * @hidden @internal
681
     */
682
    public override autoGenerate = true;
683

×
684
    /**
685
     * @hidden @internal
686
     */
687
    public override actionStrip: IgxActionStripComponent;
688

689
    /**
×
690
     * @hidden @internal
691
     */
692
    public override shouldGenerate: boolean;
693

694
    /**
695
     * @hidden @internal
1,925✔
696
     */
697
    public override moving = false;
698

699
    /**
700
     * @hidden @internal
701
     */
×
702
    public override toolbarExporting = new EventEmitter<IGridToolbarExportEventArgs>();
703

704
    /**
705
     * @hidden @internal
706
     */
707
    @Input()
7✔
708
    public override get rowDraggable(): boolean {
709
        return;
710
    }
711

712

713
    public override set rowDraggable(_val: boolean) {
26,270✔
714
    }
715

716
    /**
717
     * @hidden @internal
718
     */
719
    @Input()
8,023✔
720
    public override get allowAdvancedFiltering() {
721
        return false;
722
    }
723

724
    public override set allowAdvancedFiltering(_value) {
725
    }
726

727
    /**
728
     * @hidden @internal
729
     */
730
    @Input()
731
    public override get filterMode() {
732
        return FilterMode.quickFilter;
733
    }
734

×
735
    public override set filterMode(_value: FilterMode) {
×
736
    }
737

738
    /**
739
     * @hidden @internal
740
     */
741
    @Input()
742
    public override get allowFiltering() {
743
        return false;
744
    }
745

746
    public override set allowFiltering(_value) {
747
    }
748

749
    /**
750
     * @hidden @internal
751
     */
752
    @Input()
753
    public override get page(): number {
754
        return 0;
53✔
755
    }
320✔
756

757
    public override set page(_val: number) {
758
    }
759

760
    /**
761
     * @hidden @internal
×
762
     */
763
    @Input()
764
    public override get perPage(): number {
765
        return;
766
    }
767

×
768
    public override set perPage(_val: number) {
769
    }
770

771
    /**
772
     * @hidden @internal
×
773
     */
×
774
    public override get pinnedColumns(): IgxColumnComponent[] {
775
        return [];
776
    }
777

778
    /**
×
779
    * @hidden @internal
×
780
    */
781
    public override get unpinnedColumns(): IgxColumnComponent[] {
782
        return super.unpinnedColumns;
783
    }
784

695✔
785
    /**
2,401✔
786
    * @hidden @internal
787
    */
788
    public override get unpinnedDataView(): any[] {
789
        return super.unpinnedDataView;
790
    }
791

3,716✔
792
    /**
793
    * @hidden @internal
794
    */
145✔
795
    public override get unpinnedWidth() {
796
        return super.unpinnedWidth;
145✔
797
    }
798

799
    /**
5!
800
     * @hidden @internal
×
801
     */
5✔
802
    public override get pinnedWidth() {
88!
803
        return super.pinnedWidth;
8✔
804
    }
4✔
805

4✔
806
    /**
4✔
807
     * @hidden @internal
808
     */
3✔
809
    @Input()
3✔
810
    public override set summaryRowHeight(_value: number) {
811
    }
812

813
    public override get summaryRowHeight(): number {
1✔
814
        return 0;
1✔
815
    }
816

817
    /**
818
     * @hidden @internal
5!
819
     */
2✔
820
    public override get transactions(): TransactionService<Transaction, State> {
2✔
821
        return this._transactions;
1✔
822
    }
1!
823

1✔
824

825

826
    /**
×
827
     * @hidden @internal
828
     */
829
    public override get dragIndicatorIconTemplate(): TemplateRef<any> {
830
        return;
831
    }
832

833
    public override set dragIndicatorIconTemplate(_val: TemplateRef<any>) {
834
    }
206✔
835

836
    /**
837
     * @hidden @internal
838
     */
839
    @WatchChanges()
840
    @Input()
841
    public override get rowEditable(): boolean {
842
        return;
843
    }
844

845
    public override set rowEditable(_val: boolean) {
846
    }
847

848
    /**
2!
849
     * @hidden @internal
4✔
850
     */
19✔
851
    @Input()
10✔
852
    public override get pinning() {
2✔
853
        return {};
2✔
854
    }
2✔
855
    public override set pinning(_value) {
2✔
856
    }
857

858
    /**
859
     * @hidden @internal
860
     */
861
    @Input()
862
    public override get summaryPosition() {
863
        return;
864
    }
865

866
    public override set summaryPosition(_value: GridSummaryPosition) {
867
    }
868

869
    /**
870
     * @hidden @interal
871
     */
12✔
872
    @Input()
12✔
873
    public override get summaryCalculationMode() {
11✔
874
        return;
875
    }
876

1✔
877
    public override set summaryCalculationMode(_value: GridSummaryCalculationMode) {
878
    }
12✔
879

4✔
880
    /**
881
     * @hidden @interal
12✔
882
     */
12✔
883
    @Input()
12✔
884
    public override get showSummaryOnCollapse() {
3✔
885
        return;
3✔
886
    }
887

12✔
888
    public override set showSummaryOnCollapse(_value: boolean) {
889
    }
890

891
    /**
892
     * @hidden @internal
893
     */
894
    public override get hiddenColumnsCount() {
895
        return null;
896
    }
897

898
    /**
899
     * @hidden @internal
900
     */
901
    public override get pinnedColumnsCount() {
902
        return null;
9✔
903
    }
9✔
904

1✔
905
    /**
906
     * @hidden @internal
8✔
907
     */
908
    @Input()
8✔
909
    public override get batchEditing(): boolean {
8✔
910
        return;
3✔
911
    }
912

913
    public override set batchEditing(_val: boolean) {
914
    }
915

916
    public override get selectedRows(): any[] {
917
        if (this.selectionService.getSelectedRows().length === 0) {
918
            return [];
919
        }
920
        const selectedRowIds = [];
921
        this.dataView.forEach(record => {
922
            const prev = [];
923
            for (const dim of this.rowDimensions) {
924
                let currDim = dim;
925
                let shouldBreak = false;
4✔
926
                do {
4✔
927
                    const key = PivotUtil.getRecordKey(record, currDim);
4✔
928
                    if (this.selectionService.isPivotRowSelected(key) && !selectedRowIds.find(x => x === record)) {
1✔
929
                        selectedRowIds.push(record);
930
                        shouldBreak = true;
4✔
931
                        break;
1✔
932
                    }
933
                    currDim = currDim.childLevel;
4✔
934
                } while (currDim);
4✔
935
                prev.push(dim);
936
                if (shouldBreak) {
937
                    break;
938
                }
939
            }
940

941
        });
942

943
        return selectedRowIds;
944
    }
945

946
    /**
947
     * Gets the default row height.
9✔
948
     *
9✔
949
     * @example
1✔
950
     * ```typescript
8✔
951
     * const rowHeigh = this.grid.defaultRowHeight;
8✔
952
     * ```
8✔
953
     */
3✔
954
    public override get defaultRowHeight(): number {
955
        if (this.superCompactMode) {
8✔
956
            return 24;
1✔
957
        }
958
        return super.defaultRowHeight;
8✔
959
    }
8✔
960

8✔
961
    constructor(
8✔
962
        validationService: IgxGridValidationService,
3✔
963
        selectionService: IgxGridSelectionService,
964
        colResizingService: IgxPivotColumnResizingService,
8✔
965
        gridAPI: GridBaseAPIService<IgxGridBaseDirective & GridType>,
966
        transactionFactory: IgxFlatTransactionFactory,
967
        elementRef: ElementRef<HTMLElement>,
968
        zone: NgZone,
969
        @Inject(DOCUMENT) document,
970
        cdr: ChangeDetectorRef,
971
        differs: IterableDiffers,
972
        viewRef: ViewContainerRef,
973
        appRef: ApplicationRef,
974
        injector: Injector,
975
        envInjector: EnvironmentInjector,
976
        navigation: IgxPivotGridNavigationService,
977
        filteringService: IgxFilteringService,
978
        @Inject(IgxOverlayService) overlayService: IgxOverlayService,
7✔
979
        summaryService: IgxGridSummaryService,
1✔
980
        @Optional() @Inject(DisplayDensityToken) _displayDensityOptions: IDisplayDensityOptions,
981
        @Inject(LOCALE_ID) localeId: string,
7✔
982
        platform: PlatformUtil,
7✔
983
        @Optional() @Inject(IgxGridTransaction) _diTransactions?: TransactionService<Transaction, State>) {
6✔
984
        super(
985
            validationService,
986
            selectionService,
1✔
987
            colResizingService,
988
            gridAPI,
7✔
989
            transactionFactory,
7✔
990
            elementRef,
7✔
991
            zone,
7✔
992
            document,
7✔
993
            cdr,
994
            differs,
995
            viewRef,
996
            appRef,
997
            injector,
998
            envInjector,
999
            navigation,
1000
            filteringService,
1001
            overlayService,
1002
            summaryService,
1003
            _displayDensityOptions,
1004
            localeId,
1005
            platform,
1006
            _diTransactions);
6✔
1007
    }
1✔
1008

1009
    /**
5✔
1010
     * @hidden
1011
     */
5✔
1012
    public override ngOnInit() {
1013
        // pivot grid always generates columns automatically.
1014
        this.autoGenerate = true;
1015
        super.ngOnInit();
1016
    }
1017

1018
    /**
1019
     * @hidden
1020
     */
1021
    public override ngAfterContentInit() {
1022
        // ignore any user defined columns and auto-generate based on pivot config.
1023
        this.updateColumns([]);
1024
        Promise.resolve().then(() => {
1025
            this.setupColumns();
6✔
1026
        });
6✔
1027
        if (this.valueChipTemplateDirective) {
6!
1028
            this.valueChipTemplate = this.valueChipTemplateDirective.template;
6✔
1029
        }
6✔
1030
    }
6✔
1031

6✔
1032
    /**
6✔
1033
     * @hidden @internal
1034
     */
1035
    public override ngAfterViewInit() {
1036
        Promise.resolve().then(() => {
1037
            super.ngAfterViewInit();
1038
        });
1039
    }
1040

1041
    /**
1042
     * Notifies for dimension change.
1043
     */
1044
    public notifyDimensionChange(regenerateColumns = false) {
1045
        if (regenerateColumns) {
1046
            this.setupColumns();
5✔
1047
        }
1✔
1048
        this.pipeTrigger++;
4✔
1049
        this.cdr.detectChanges();
4✔
1050
    }
4✔
1051

4✔
1052
    /**
4✔
1053
     * Gets the full list of dimensions.
4✔
1054
     *
1055
     * @example
1056
     * ```typescript
1057
     * const dimensions = this.grid.allDimensions;
1058
     * ```
1059
     */
1060
    public get allDimensions() {
1061
        const config = this._pivotConfiguration;
1062
        if (!config) return [];
1063
        return (config.rows || []).concat((config.columns || [])).concat(config.filters || []).filter(x => x !== null && x !== undefined);
1064
    }
18✔
1065

18✔
1066
    /** @hidden @internal */
1067
    public createFilterESF(dropdown: any, column: ColumnType, options: OverlaySettings, shouldReatach: boolean) {
18✔
1068
        options.outlet = this.outlet;
18✔
1069
        if (dropdown) {
6✔
1070
            dropdown.initialize(column, this.overlayService);
6✔
1071
            if (shouldReatach) {
1072
                const id = this.overlayService.attach(dropdown.element, options);
18✔
1073
                dropdown.overlayComponentId = id;
18✔
1074
                return { id, ref: undefined };
18✔
1075
            }
13✔
1076
            return { id: dropdown.overlayComponentId, ref: undefined };
1077
        }
18✔
1078
    }
18✔
1079

1080
    /** @hidden */
1081
    public override featureColumnsWidth() {
1082
        return this.pivotRowWidths;
1083
    }
1084

1085
    /**
1086
     * Gets/Sets the value of the `id` attribute.
1087
     *
1088
     * @remarks
1089
     * If not provided it will be automatically generated.
1090
     * @example
1091
     * ```html
1092
     * <igx-pivot-grid [id]="'igx-pivot-1'" [data]="Data"></igx-pivot-grid>
1093
     * ```
1094
     */
2✔
1095
    @HostBinding('attr.id')
2✔
1096
    @Input()
2✔
1097
    public get id(): string {
1✔
1098
        return this.p_id;
1099
    }
2✔
1100
    public set id(value: string) {
1101
        this.p_id = value;
1102
    }
1103

1104
    /**
1105
     * An @Input property that lets you fill the `IgxPivotGridComponent` with an array of data.
40✔
1106
     * ```html
1107
     * <igx-pivot-grid [data]="Data"></igx-pivot-grid>
14!
1108
     * ```
×
1109
     */
1110
    @Input()
14✔
1111
    public set data(value: any[] | null) {
1112
        this._data = value || [];
14!
1113
        if (!this._init) {
×
1114
            this.setupColumns();
1115
            this.reflow();
14✔
1116
        }
1117
        this.cdr.markForCheck();
11✔
1118
        if (this.height === null || this.height.indexOf('%') !== -1) {
2✔
1119
            // If the height will change based on how much data there is, recalculate sizes in igxForOf.
1120
            this.notifyChanges(true);
11✔
1121
        }
1122
    }
1✔
1123

1124
    /**
1125
     * Returns an array of data set to the component.
1126
     * ```typescript
1127
     * let data = this.grid.data;
1128
     * ```
1129
     */
4✔
1130
    public get data(): any[] | null {
4✔
1131
        return this._data;
1✔
1132
    }
1133

1134
    /**
3✔
1135
     * @hidden
1136
     */
1137
    public getContext(rowData, rowIndex): any {
4✔
1138
        return {
4✔
1139
            $implicit: rowData,
1140
            templateID: {
1141
                type: 'dataRow',
1142
                id: null
1143
            },
1144
            index: this.getDataViewIndex(rowIndex, false)
1145
        };
12✔
1146
    }
12✔
1147

1✔
1148
    /**
11✔
1149
     * @hidden @internal
11✔
1150
     */
11✔
1151
    public get pivotRowWidths() {
11✔
1152
        return this.rowDimensions.length ? this.rowDimensions.reduce((accumulator, dim) => accumulator + this.rowDimensionWidthToPixels(dim), 0) :
11✔
1153
            this.rowDimensionWidthToPixels(this.emptyRowDimension);
1154
    }
1155

56✔
1156
    /**
38✔
1157
     * @hidden @internal
39✔
1158
     */
1159
    public rowDimensionWidthToPixels(dim: IPivotDimension, ignoreBeforeInit = false): number {
1160
        if (!ignoreBeforeInit && this.shouldGenerate) {
1161
            return 0;
2✔
1162
        }
2!
1163

2✔
1164
        if (!dim.width) {
10✔
1165
            return MINIMUM_COLUMN_WIDTH;
2✔
1166
        }
2✔
1167
        const isPercent = dim.width && dim.width.indexOf('%') !== -1;
2✔
1168
        if (isPercent) {
1169
            return parseFloat(dim.width) / 100 * this.calcWidth;
2✔
1170
        } else {
1171
            return parseInt(dim.width, 10);
2✔
1172
        }
2✔
1173
    }
2!
1174

×
1175
    /**
1176
     * @hidden @internal
1177
     */
2✔
1178
    public reverseDimensionWidthToPercent(width: number): number {
1179
        return (width * 100 / this.calcWidth);
1180
    }
1181

1182
    /** @hidden @internal */
1183
    public get pivotContentCalcWidth() {
1184
        const totalDimWidth = this.rowDimensions.length > 0 ?
126,406✔
1185
            this.rowDimensions.map((dim) => this.rowDimensionWidthToPixels(dim)).reduce((prev, cur) => prev + cur) :
1186
            0;
1187
        return this.calcWidth - totalDimWidth;
1188
    }
1189

1190
    /** @hidden @internal */
1191
    public get pivotPinnedWidth() {
3,080✔
1192
        return !this.shouldGenerate ? (this.isPinningToStart ? this.pinnedWidth : this.headerFeaturesWidth) : 0;
3,080✔
1193
    }
1194

1195
    /** @hidden @internal */
1196
    public get pivotUnpinnedWidth() {
1197
        return !this.shouldGenerate ? this.unpinnedWidth : 0;
1198
    }
1199

3,080✔
1200
    /** @hidden @internal */
3,080✔
1201
    public get rowDimensions() {
1202
        return this.pivotConfiguration.rows?.filter(x => x.enabled) || [];
1203
    }
8!
1204

×
1205
    /** @hidden @internal */
8✔
1206
    public get columnDimensions() {
8✔
1207
        return this.pivotConfiguration.columns?.filter(x => x.enabled) || [];
8✔
1208
    }
44✔
1209

3✔
1210
    /** @hidden @internal */
8✔
1211
    public get filterDimensions() {
44✔
1212
        return this.pivotConfiguration.filters?.filter(x => x.enabled) || [];
3✔
1213
    }
8✔
1214

18✔
1215
    /** @hidden @internal */
18✔
1216
    public get values() {
11✔
1217
        return this.pivotConfiguration.values?.filter(x => x.enabled) || [];
1218
    }
1219

7✔
1220
    public toggleColumn(col: IgxColumnComponent) {
1221
        const state = this.columnGroupStates.get(col.field);
1222
        const newState = !state;
8✔
1223
        this.columnGroupStates.set(col.field, newState);
1✔
1224
        this.toggleRowGroup(col, newState);
3✔
1225
        this.reflow();
3✔
1226
    }
1227

1228
    protected override getColumnWidthSum(): number {
1229
        let colSum = super.getColumnWidthSum();
1230
        colSum += this.rowDimensions.map(dim => this.rowDimensionWidthToPixels(dim, true)).reduce((prev, cur) => prev + cur, 0);
1231
        return colSum;
1232
    }
1233

1234
    /**
1235
     * @hidden @internal
1236
     */
267✔
1237
    public override isRecordPinnedByIndex(_rowIndex: number) {
1238
        return null;
1239
    }
1240

1241
    /**
1242
     * @hidden @internal
45!
1243
     */
45✔
1244
    public override toggleColumnVisibility(_args: IColumnVisibilityChangedEventArgs) {
1245
        return;
1246
    }
4✔
1247

4✔
1248
    /**
8✔
1249
     * @hidden @internal
1250
     */
4✔
1251
    public override expandAll() {
1252
    }
1253

×
1254
    /**
×
1255
     * @hidden @internal
1256
     */
×
1257
    public override collapseAll() {
1258
    }
1259

1260
    /**
1261
     * @hidden @internal
1262
     */
206✔
1263
    public override expandRow(_rowID: any) {
206✔
1264
    }
206✔
1265

215✔
1266
    /**
206✔
1267
     * @hidden @internal
206✔
1268
     */
206✔
1269
    public override collapseRow(_rowID: any) {
12✔
1270
    }
1271

1272
    /**
206✔
1273
     * @hidden @internal
4✔
1274
     */
4✔
1275
    public override get pinnedRows(): IgxGridRowComponent[] {
2✔
1276
        return;
4✔
1277
    }
2✔
1278

12✔
1279
    /**
1280
     * @hidden @internal
1281
     */
2✔
1282
    @Input()
1283
    public override get totalRecords(): number {
1284
        return;
202✔
1285
    }
1286

204✔
1287
    public override set totalRecords(_total: number) {
204✔
1288
    }
1289

204✔
1290
    /**
1!
1291
     * @hidden @internal
1✔
1292
     */
14✔
1293
    public override moveColumn(_column: IgxColumnComponent, _target: IgxColumnComponent, _pos: DropPosition = DropPosition.AfterDropTarget) {
1✔
1294
    }
1!
1295

1✔
1296
    /**
1297
     * @hidden @internal
1298
     */
1299
    public override addRow(_data: any): void {
204✔
1300
    }
204✔
1301

204!
1302
    /**
204✔
1303
     * @hidden @internal
1304
     */
1305
    public override deleteRow(_rowSelector: any): any {
1306
    }
706✔
1307

4✔
1308
    /**
1309
     * @hidden @internal
702✔
1310
     */
1311
    public override updateCell(_value: any, _rowSelector: any, _column: string): void {
1312
    }
524✔
1313

209✔
1314
    /**
209✔
1315
     * @hidden @internal
524✔
1316
     */
524✔
1317
    public override updateRow(_value: any, _rowSelector: any): void {
524✔
1318
    }
524✔
1319

1320
    /**
209✔
1321
     * @hidden @internal
1322
     */
1323
    public override enableSummaries(..._rest) {
2✔
1324
    }
8✔
1325

2✔
1326
    /**
2✔
1327
     * @hidden @internal
8✔
1328
     */
8✔
1329
    public override disableSummaries(..._rest) {
8✔
1330
    }
8✔
1331

8✔
1332
    /**
8✔
1333
     * @hidden @internal
8!
1334
     */
8✔
1335
    public override pinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
8✔
1336
        return;
1337
    }
8✔
1338

1339
    /**
1340
     * @hidden @internal
2✔
1341
     */
1342
    public override unpinColumn(_columnName: string | IgxColumnComponent, _index?): boolean {
204✔
1343
        return;
268✔
1344
    }
268✔
1345

12✔
1346
    /**
12✔
1347
     * @hidden @internal
12✔
1348
     */
12✔
1349
    public override pinRow(_rowID: any, _index?: number, _row?: RowType): boolean {
12✔
1350
        return;
12✔
1351
    }
12✔
1352

12✔
1353
    /**
12✔
1354
     * @hidden @internal
1355
     */
12✔
1356
    public override unpinRow(_rowID: any, _row?: RowType): boolean {
1357
        return;
256✔
1358
    }
256✔
1359

861✔
1360
    /**
861!
1361
     * @hidden @internal
×
1362
     */
1363
    public override get pinnedRowHeight() {
861✔
1364
        return;
797✔
1365
    }
797✔
1366

797✔
1367
    /**
641✔
1368
     * @hidden @internal
641✔
1369
     */
641✔
1370
    public override get hasEditableColumns(): boolean {
1371
        return;
1372
    }
64!
1373

64✔
1374
    /**
64✔
1375
     * @hidden @internal
21✔
1376
     */
1377
    public override get hasSummarizedColumns(): boolean {
64✔
1378
        return;
456✔
1379
    }
64✔
1380

64✔
1381
    /**
63✔
1382
     * @hidden @internal
63✔
1383
     */
1384
    public override get hasMovableColumns(): boolean {
63✔
1385
        return;
63✔
1386
    }
63✔
1387

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

1395
    /**
1✔
1396
     * @hidden @internal
1✔
1397
     */
1!
1398
    public override openAdvancedFilteringDialog(_overlaySettings?: OverlaySettings) {
1✔
1399
    }
1✔
1400

1401
    /**
1402
     * @hidden @internal
1403
     */
1404
    public override closeAdvancedFilteringDialog(_applyChanges: boolean) {
256✔
1405
    }
1406

1407
    /**
882✔
1408
     * @hidden @internal
882✔
1409
     */
1410
    public override endEdit(_commit = true, _event?: Event): boolean {
1411
        return;
882✔
1412
    }
882✔
1413

882✔
1414
    /**
882!
1415
     * @hidden @internal
×
1416
     */
1417
    public override beginAddRowById(_rowID: any, _asChild?: boolean): void {
882✔
1418
    }
882✔
1419

882✔
1420
    /**
882✔
1421
     * @hidden @internal
882✔
1422
     */
882✔
1423
    public override beginAddRowByIndex(_index: number): void {
1424
    }
1425

×
1426
    /**
×
1427
     * @hidden @internal
1428
     */
×
1429
    public override clearSearch() { }
1430

1431
    /**
724✔
1432
    * @hidden @internal
724✔
1433
    */
724✔
1434
    public override refreshSearch(_updateActiveInfo?: boolean, _endEdit = true): number {
724!
1435
        return 0;
724✔
1436
    }
1,453✔
1437

1,453✔
1438
    /**
1,453✔
1439
    * @hidden @internal
1,453✔
1440
    */
1,453!
1441
    public override findNext(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
×
1442
        return 0;
1443
    }
1,453✔
1444

1,453✔
1445
    /**
1,453✔
1446
    * @hidden @internal
1,453✔
1447
    */
1,453✔
1448
    public override findPrev(_text: string, _caseSensitive?: boolean, _exactMatch?: boolean): number {
1,453✔
1449
        return 0;
1450
    }
724✔
1451

1452
    /**
1453
    * @hidden @internal
1454
    */
1455
    public override getNextCell(currRowIndex: number, curVisibleColIndex: number,
1456
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
1,544✔
1457
        return super.getNextCell(currRowIndex, curVisibleColIndex, callback);
1,544✔
1458
    }
1459

28✔
1460
    /**
1461
    * @hidden @internal
1,516✔
1462
    */
1463
    public override getPreviousCell(currRowIndex: number, curVisibleColIndex: number,
1464
        callback: (IgxColumnComponent) => boolean = null): ICellPosition {
121✔
1465
        return super.getPreviousCell(currRowIndex, curVisibleColIndex, callback);
121✔
1466
    }
413✔
1467

1468
    /**
121✔
1469
    * @hidden @internal
121✔
1470
    */
211✔
1471
    public override getPinnedWidth(takeHidden = false) {
1472
        return super.getPinnedWidth(takeHidden);
1473
    }
2✔
1474

1475
    /**
1476
     * @hidden @internal
1477
     */
1478
    public override get totalHeight() {
1479
        return this.calcHeight;
1480
    }
1481

1482
    public getColumnGroupExpandState(col: IgxColumnComponent) {
1483
        const state = this.columnGroupStates.get(col.field);
1484
        // columns are expanded by default?
1485
        return state !== undefined && state !== null ? state : false;
1486
    }
1487

1488
    public toggleRowGroup(col: IgxColumnComponent, newState: boolean) {
1489
        if (!col) return;
1490
        if (this.hasMultipleValues) {
1491
            const parentCols = col.parent ? col.parent.children.toArray() : this._autoGeneratedCols.filter(x => x.level === 0);
1492
            const siblingCol = parentCols.filter(x => x.header === col.header && x !== col)[0];
1493
            const currIndex = parentCols.indexOf(col);
1494
            const siblingIndex = parentCols.indexOf(siblingCol);
1495
            if (currIndex < siblingIndex) {
1496
                // clicked on the full hierarchy header
1497
                this.resolveToggle(col, newState);
2✔
1498
                siblingCol.headerTemplate = this.headerTemplate;
1499
            } else {
1500
                // clicked on summary parent column that contains just the measures
1501
                col.headerTemplate = undefined;
1502
                this.resolveToggle(siblingCol, newState);
1503
            }
1504
        } else {
1505
            const parentCols = col.parent ? col.parent.children : this._autoGeneratedCols.filter(x => x.level === 0);
1506
            const fieldColumn = parentCols.filter(x => x.header === col.header && !x.columnGroup)[0];
1507
            const groupColumn = parentCols.filter(x => x.header === col.header && x.columnGroup)[0];
1508
            this.resolveToggle(groupColumn, newState);
1509
            if (newState) {
1510
                fieldColumn.headerTemplate = this.headerTemplate;
1511
            } else {
1512
                fieldColumn.headerTemplate = undefined;
1513
            }
1514
        }
1515
    }
1516

1517
    /**
1518
    * @hidden @internal
1519
    */
1520
    public override setupColumns() {
1521
        super.setupColumns();
1522
    }
1523

1524
    /**
1525
     * Auto-sizes row dimension cells.
1526
     *
1527
     * @remarks
1528
     * Only sizes based on the dimension cells in view.
1529
     * @example
1530
     * ```typescript
1531
     * this.grid.autoSizeRowDimension(dimension);
1532
     * ```
1533
     * @param dimension The row dimension to size.
1534
     */
1535
    public autoSizeRowDimension(dimension: IPivotDimension) {
1536
        if (this.getDimensionType(dimension) === PivotDimensionType.Row) {
1537
            const relatedDims = PivotUtil.flatten([dimension]).map(x => x.memberName);
1538
            const content = this.rowDimensionContentCollection.filter(x => relatedDims.indexOf(x.dimension.memberName) !== -1);
1539
            const headers = content.map(x => x.headerGroups.toArray()).flat().map(x => x.header && x.header.refInstance);
1540
            const autoWidth = this.getLargesContentWidth(headers);
1541
            dimension.width = autoWidth;
1542
            this.pipeTrigger++;
1543
            this.cdr.detectChanges();
1544
        }
1545
    }
1546

1547
    /**
1548
     * Inserts dimension in target collection by type at specified index or at the collection's end.
1549
     *
1550
     * @example
1551
     * ```typescript
1552
     * this.grid.insertDimensionAt(dimension, PivotDimensionType.Row, 1);
1553
     * ```
1554
     * @param dimension The dimension that will be added.
1555
     * @param targetCollectionType The target collection type to add to. Can be Row, Column or Filter.
1556
     * @param index The index in the collection at which to add.
1557
     * This parameter is optional. If not set it will add it to the end of the collection.
1558
     */
1559
    public insertDimensionAt(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1560
        const targetCollection = this.getDimensionsByType(targetCollectionType);
1561
        if (index !== undefined) {
1562
            targetCollection.splice(index, 0, dimension);
1563
        } else {
1564
            targetCollection.push(dimension);
1565
        }
1566
        if (targetCollectionType === PivotDimensionType.Column) {
2✔
1567
            this.setupColumns();
1568
        }
1569
        this.pipeTrigger++;
2✔
1570
        this.dimensionsChange.emit({ dimensions: targetCollection, dimensionCollectionType: targetCollectionType });
1571
        if (targetCollectionType === PivotDimensionType.Filter) {
1572
            this.dimensionDataColumns = this.generateDimensionColumns();
2✔
1573
            this.reflow();
1574
        }
1575
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
1576
    }
1577

1578
    /**
1579
     * Move dimension from its currently collection to the specified target collection by type at specified index or at the collection's end.
1580
     *
1581
     * @example
1582
     * ```typescript
1583
     * this.grid.moveDimension(dimension, PivotDimensionType.Row, 1);
1584
     * ```
1585
     * @param dimension The dimension that will be moved.
1586
     * @param targetCollectionType The target collection type to move it to. Can be Row, Column or Filter.
1587
     * @param index The index in the collection at which to add.
1588
     * This parameter is optional. If not set it will add it to the end of the collection.
1589
     */
1590
    public moveDimension(dimension: IPivotDimension, targetCollectionType: PivotDimensionType, index?: number) {
1591
        const prevCollectionType = this.getDimensionType(dimension);
1592
        if (prevCollectionType === null) return;
1593
        // remove from old collection
1594
        this._removeDimensionInternal(dimension);
1595
        // add to target
1596
        this.insertDimensionAt(dimension, targetCollectionType, index);
1597

1598
        if (prevCollectionType === PivotDimensionType.Column) {
1599
            this.setupColumns();
1600
        }
1601
    }
1602

1603
    /**
1604
     * Removes dimension from its currently collection.
1605
     * @remarks
1606
     * This is different than toggleDimension that enabled/disables the dimension.
1607
     * This completely removes the specified dimension from the collection.
1608
     * @example
1609
     * ```typescript
1610
     * this.grid.removeDimension(dimension);
1611
     * ```
1612
     * @param dimension The dimension to be removed.
1613
     */
1614
    public removeDimension(dimension: IPivotDimension) {
1615
        const prevCollectionType = this.getDimensionType(dimension);
1616
        this._removeDimensionInternal(dimension);
1617
        if (prevCollectionType === PivotDimensionType.Column) {
1618
            this.setupColumns();
1619
        }
1620
        if (prevCollectionType === PivotDimensionType.Filter) {
1621
            this.reflow();
1622
        }
1623
        this.pipeTrigger++;
1624
        this.cdr.detectChanges();
1625
    }
1626

1627
    /**
1628
     * Toggles the dimension's enabled state on or off.
1629
     * @remarks
1630
     * The dimension remains in its current collection. This just changes its enabled state.
1631
     * @example
1632
     * ```typescript
1633
     * this.grid.toggleDimension(dimension);
1634
     * ```
1635
     * @param dimension The dimension to be toggled.
1636
     */
1637
    public toggleDimension(dimension: IPivotDimension) {
1638
        const dimType = this.getDimensionType(dimension);
1639
        if (dimType === null) return;
1640
        const collection = this.getDimensionsByType(dimType);
1641
        dimension.enabled = !dimension.enabled;
1642
        if (dimType === PivotDimensionType.Column) {
1643
            this.setupColumns();
1644
        }
1645
        if (!dimension.enabled && dimension.filter) {
1646
            this.filteringService.clearFilter(dimension.memberName);
1647
        }
1648
        this.pipeTrigger++;
1649
        this.dimensionsChange.emit({ dimensions: collection, dimensionCollectionType: dimType });
1650
        this.cdr.detectChanges();
1651
        if (dimType === PivotDimensionType.Filter) {
1652
            this.reflow();
1653
        }
1654
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
1655
    }
1656

1657
    /**
1658
     * Inserts value at specified index or at the end.
1659
     *
1660
     * @example
1661
     * ```typescript
1662
     * this.grid.insertValueAt(value, 1);
1663
     * ```
1664
     * @param value The value definition that will be added.
1665
     * @param index The index in the collection at which to add.
1666
     * This parameter is optional. If not set it will add it to the end of the collection.
1667
     */
1668
    public insertValueAt(value: IPivotValue, index?: number) {
1669
        if (!this.pivotConfiguration.values) {
1670
            this.pivotConfiguration.values = [];
1671
        }
1672
        const values = this.pivotConfiguration.values;
1673
        if (index !== undefined) {
1674
            values.splice(index, 0, value);
1675
        } else {
1676
            values.push(value);
1677
        }
1678
        this.setupColumns();
1679
        this.pipeTrigger++;
1680
        this.cdr.detectChanges();
1681
        this.valuesChange.emit({ values });
1682
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
1683
    }
1684

1685
    /**
1686
     * Move value from its currently at specified index or at the end.
1687
     *
1688
     * @example
1689
     * ```typescript
1690
     * this.grid.moveValue(value, 1);
1691
     * ```
1692
     * @param value The value that will be moved.
1693
     * @param index The index in the collection at which to add.
1694
     * This parameter is optional. If not set it will add it to the end of the collection.
1695
     */
1696
    public moveValue(value: IPivotValue, index?: number) {
1697
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
1698
        // remove from old index
1699
        this.removeValue(value);
1700
        // add to new
1701
        this.insertValueAt(value, index);
1702
    }
1703

1704
    /**
1705
     * Removes value from collection.
1706
     * @remarks
1707
     * This is different than toggleValue that enabled/disables the value.
1708
     * This completely removes the specified value from the collection.
1709
     * @example
1710
     * ```typescript
1711
     * this.grid.removeValue(dimension);
1712
     * ```
1713
     * @param value The value to be removed.
1714
     */
1715
    public removeValue(value: IPivotValue,) {
1716
        const values = this.pivotConfiguration.values;
1717
        const currentIndex = values.indexOf(value);
1718
        if (currentIndex !== -1) {
1719
            values.splice(currentIndex, 1);
1720
            this.setupColumns();
1721
            this.pipeTrigger++;
1722
            this.valuesChange.emit({ values });
1723
            this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
1724
        }
1725
    }
1726

1727
    /**
1728
     * Toggles the value's enabled state on or off.
1729
     * @remarks
1730
     * The value remains in its current collection. This just changes its enabled state.
1731
     * @example
1732
     * ```typescript
1733
     * this.grid.toggleValue(value);
1734
     * ```
1735
     * @param value The value to be toggled.
1736
     */
1737
    public toggleValue(value: IPivotValue) {
1738
        if (this.pivotConfiguration.values.indexOf(value) === -1) return;
1739
        value.enabled = !value.enabled;
1740
        this.setupColumns();
1741
        this.pipeTrigger++;
1742
        this.valuesChange.emit({ values: this.pivotConfiguration.values });
1743
        this.reflow();
1744
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
1745
    }
1746

1747
    /**
1748
     * Sort the dimension and its children in the provided direction.
1749
     * @example
1750
     * ```typescript
1751
     * this.grid.sortDimension(dimension, SortingDirection.Asc);
1752
     * ```
1753
     * @param value The value to be toggled.
1754
     */
1755
    public sortDimension(dimension: IPivotDimension, sortDirection: SortingDirection) {
1756
        const dimensionType = this.getDimensionType(dimension);
1757
        dimension.sortDirection = sortDirection;
1758
        // apply same sort direction to children.
1759
        let dim = dimension;
1760
        while (dim.childLevel) {
1761
            dim.childLevel.sortDirection = dimension.sortDirection;
1762
            dim = dim.childLevel;
1763
        }
1764
        this.pipeTrigger++;
1765
        this.dimensionsSortingExpressionsChange.emit(this.dimensionsSortingExpressions);
1766
        if (dimensionType === PivotDimensionType.Column) {
1767
            this.setupColumns();
1768
        }
1769
        this.cdr.detectChanges();
1770
        this.pivotConfigurationChange.emit({ pivotConfiguration: this.pivotConfiguration });
1771
    }
1772

1773
    /**
1774
     * Filters a single `IPivotDimension`.
1775
     *
1776
     * @example
1777
     * ```typescript
1778
     * public filter() {
1779
     *      const set = new Set();
1780
     *      set.add('Value 1');
1781
     *      set.add('Value 2');
1782
     *      this.grid1.filterDimension(this.pivotConfigHierarchy.rows[0], set, IgxStringFilteringOperand.instance().condition('in'));
1783
     * }
1784
     * ```
1785
     */
1786
    public filterDimension(dimension: IPivotDimension, value: any, conditionOrExpressionTree?: IFilteringOperation | IFilteringExpressionsTree ) {
1787
        this.filteringService.filter(dimension.memberName, value, conditionOrExpressionTree);
1788
        const dimensionType = this.getDimensionType(dimension);
1789
        if (dimensionType === PivotDimensionType.Column) {
1790
            this.setupColumns();
1791
        }
1792
        this.cdr.detectChanges();
1793
    }
1794

1795
    /**
1796
     * @hidden @internal
1797
     */
1798
    public getDimensionsByType(dimension: PivotDimensionType) {
1799
        switch (dimension) {
1800
            case PivotDimensionType.Row:
1801
                if (!this.pivotConfiguration.rows) {
1802
                    this.pivotConfiguration.rows = [];
1803
                }
1804
                return this.pivotConfiguration.rows;
1805
            case PivotDimensionType.Column:
1806
                if (!this.pivotConfiguration.columns) {
1807
                    this.pivotConfiguration.columns = [];
1808
                }
1809
                return this.pivotConfiguration.columns;
1810
            case PivotDimensionType.Filter:
1811
                if (!this.pivotConfiguration.filters) {
1812
                    this.pivotConfiguration.filters = [];
1813
                }
1814
                return this.pivotConfiguration.filters;
1815
            default:
1816
                return null;
1817
        }
1818
    }
1819

1820
    /**
1821
     * @hidden @internal
1822
     */
1823
    public resizeRowDimensionPixels(dimension: IPivotDimension, newWidth: number) {
1824
        const isPercentageWidth = dimension.width && typeof dimension.width === 'string' && dimension.width.indexOf('%') !== -1;
1825
        if (isPercentageWidth) {
1826
            dimension.width = this.reverseDimensionWidthToPercent(newWidth).toFixed(2) + '%';
1827
        } else {
1828
            dimension.width = newWidth + 'px';
1829
        }
1830

1831
        // Notify the grid to reflow, to update if horizontal scrollbar needs to be rendered/removed.
1832
        this.pipeTrigger++;
1833
        this.cdr.detectChanges();
1834
    }
1835

1836
    /*
1837
    * @hidden
1838
    * @internal
1839
    */
1840
    protected _removeDimensionInternal(dimension) {
1841
        const prevCollectionType = this.getDimensionType(dimension);
1842
        if (prevCollectionType === null) return;
1843
        const prevCollection = this.getDimensionsByType(prevCollectionType);
1844
        const currentIndex = prevCollection.indexOf(dimension);
1845
        prevCollection.splice(currentIndex, 1);
1846
        this.pipeTrigger++;
1847
        this.cdr.detectChanges();
1848
    }
1849

1850
    protected getDimensionType(dimension: IPivotDimension): PivotDimensionType {
1851
        return PivotUtil.flatten(this.pivotConfiguration.rows).indexOf(dimension) !== -1 ? PivotDimensionType.Row :
1852
            PivotUtil.flatten(this.pivotConfiguration.columns).indexOf(dimension) !== -1 ? PivotDimensionType.Column :
1853
                (!!this.pivotConfiguration.filters && PivotUtil.flatten(this.pivotConfiguration.filters).indexOf(dimension) !== -1) ?
1854
                    PivotDimensionType.Filter : null;
1855
    }
1856

1857
    protected getLargesContentWidth(contents: ElementRef[]): string {
1858
        const largest = new Map<number, number>();
1859
        if (contents.length > 0) {
1860
            const cellsContentWidths = [];
1861
            contents.forEach((elem) => cellsContentWidths.push(this.getHeaderCellWidth(elem.nativeElement).width));
1862
            const index = cellsContentWidths.indexOf(Math.max(...cellsContentWidths));
1863
            const cellStyle = this.document.defaultView.getComputedStyle(contents[index].nativeElement);
1864
            const cellPadding = parseFloat(cellStyle.paddingLeft) + parseFloat(cellStyle.paddingRight) +
1865
                parseFloat(cellStyle.borderLeftWidth) + parseFloat(cellStyle.borderRightWidth);
1866
            largest.set(Math.max(...cellsContentWidths), cellPadding);
1867
        }
1868
        const largestCell = Math.max(...Array.from(largest.keys()));
1869
        const width = Math.ceil(largestCell + largest.get(largestCell));
1870

1871
        if (Number.isNaN(width)) {
1872
            return null;
1873
        } else {
1874
            return width + 'px';
1875
        }
1876
    }
1877

1878
    /**
1879
    * @hidden
1880
    */
1881
    public get hasMultipleValues() {
1882
        return this.values.length > 1;
1883
    }
1884

1885
    /**
1886
    * @hidden
1887
    */
1888
    public get excelStyleFilterMaxHeight() {
1889
        // max 10 rows, row size depends on density
1890
        const maxHeight = this.renderedRowHeight * 10;
1891
        return `${maxHeight}px`;
1892
    }
1893

1894
    /**
1895
    * @hidden
1896
    */
1897
    public get excelStyleFilterMinHeight(): string {
1898
        // min 5 rows, row size depends on density
1899
        const minHeight = this.renderedRowHeight * 5;
1900
        return `${minHeight}px`;
1901
    }
1902

1903
    protected resolveToggle(groupColumn: IgxColumnComponent, state: boolean) {
1904
        if (!groupColumn) return;
1905
        groupColumn.hidden = state;
1906
        this.columnGroupStates.set(groupColumn.field, state);
1907
        const childrenTotal = this.hasMultipleValues ?
1908
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === this.values.length) :
1909
            groupColumn.children.filter(x => !x.columnGroup);
1910
        const childrenSubgroups = this.hasMultipleValues ?
1911
            groupColumn.children.filter(x => x.columnGroup && x.children.filter(y => !y.columnGroup).length === 0) :
1912
            groupColumn.children.filter(x => x.columnGroup);
1913
        childrenTotal.forEach(group => {
1914
            const newState = this.columnGroupStates.get(group.field) || state;
1915
            if (newState) {
1916
                group.headerTemplate = this.headerTemplate;
1917
            } else {
1918
                group.headerTemplate = undefined;
1919
            }
1920
        });
1921
        if (!groupColumn.hidden && childrenSubgroups.length > 0) {
1922
            childrenSubgroups.forEach(group => {
1923
                const newState = this.columnGroupStates.get(group.field) || state;
1924
                this.resolveToggle(group, newState);
1925
            });
1926
        }
1927
    }
1928

1929
    /**
1930
     * @hidden
1931
     * @internal
1932
     */
1933
    protected override calcGridHeadRow() {
1934
    }
1935

1936
    protected override buildDataView(data: any[]) {
1937
        this._dataView = data;
1938
    }
1939

1940
    /**
1941
     * @hidden @internal
1942
     */
1943
    protected override getDataBasedBodyHeight(): number {
1944
        const dvl = this.dataView?.length || 0;
1945
        return dvl < this._defaultTargetRecordNumber ? 0 : this.defaultTargetBodyHeight;
1946
    }
1947

1948
    protected override horizontalScrollHandler(event) {
1949
        const scrollLeft = event.target.scrollLeft;
1950
        this.theadRow.headerContainers.forEach(headerForOf => {
1951
            headerForOf.onHScroll(scrollLeft);
1952
        });
1953
        super.horizontalScrollHandler(event);
1954
    }
1955

1956
    protected override verticalScrollHandler(event) {
1957
        this.verticalRowDimScrollContainers.forEach(x => {
1958
            x.onScroll(event);
1959
        });
1960
        super.verticalScrollHandler(event);
1961
    }
1962

1963
    /**
1964
     * @hidden
1965
     */
1966
    protected override autogenerateColumns() {
1967
        let columns = [];
1968
        const data = this.gridAPI.filterDataByExpressions(this.filteringExpressionsTree);
1969
        this.dimensionDataColumns = this.generateDimensionColumns();
1970
        const flattenedColumnsWithSorting = PivotUtil.flatten(this.columnDimensions).filter(dim => dim.sortDirection);
1971
        const expressions =  flattenedColumnsWithSorting.length > 0? PivotSortUtil.generateDimensionSortingExpressions(flattenedColumnsWithSorting) : [];
1972
        let sortedData = data;
1973
        if (expressions.length > 0) {
1974
            sortedData = DataUtil.sort(cloneArray(data), expressions, this.sortStrategy, this);
1975
        }
1976
        let fieldsMap;
1977
        if (this.pivotConfiguration.columnStrategy && this.pivotConfiguration.columnStrategy instanceof NoopPivotDimensionsStrategy) {
1978
            const fields = this.generateDataFields(sortedData);
1979
            if (fields.length === 0) return;
1980
            const rowFields = PivotUtil.flatten(this.pivotConfiguration.rows).map(x => x.memberName);
1981
            const keyFields = Object.values(this.pivotKeys);
1982
            const filteredFields = fields.filter(x => rowFields.indexOf(x) === -1 && keyFields.indexOf(x) === -1 &&
1983
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.level) === -1 &&
1984
                x.indexOf(this.pivotKeys.rowDimensionSeparator + this.pivotKeys.records) === -1);
1985
            fieldsMap = this.generateFromData(filteredFields);
1986
        } else {
1987
            fieldsMap = PivotUtil.getFieldsHierarchy(
1988
                sortedData,
1989
                this.columnDimensions,
1990
                PivotDimensionType.Column,
1991
                this.pivotKeys,
1992
                this.pivotValueCloneStrategy
1993
            );
1994
        }
1995
        columns = this.generateColumnHierarchy(fieldsMap, sortedData);
1996
        this._autoGeneratedCols = columns;
1997
        // reset expansion states if any are stored.
1998
        this.columnGroupStates.forEach((value, key) => {
1999
            if (value) {
2000
                const primaryColumn = columns.find(x => x.field === key && x.headerTemplate === this.headerTemplate);
2001
                const groupSummaryColumn = columns.find(x => x.field === key && x.headerTemplate !== this.headerTemplate);
2002
                this.toggleRowGroup(primaryColumn, value);
2003
                if (groupSummaryColumn) {
2004
                    groupSummaryColumn.headerTemplate = this.headerTemplate;
2005
                }
2006
            }
2007
        });
2008

2009
        this.updateColumns(columns);
2010
        this.reflow();
2011
        if (data && data.length > 0) {
2012
            this.shouldGenerate = false;
2013
        }
2014
    }
2015

2016
    protected override getComponentDensityClass(baseStyleClass: string): string {
2017
        if (this.superCompactMode) {
2018
            return `${baseStyleClass}--${DisplayDensity.compact} igx-grid__pivot--super-compact`;
2019
        }
2020
        return super.getComponentDensityClass(baseStyleClass);
2021
    }
2022

2023
    protected generateDimensionColumns(): IgxColumnComponent[] {
2024
        const rootFields = this.allDimensions.map(x => x.memberName);
2025
        const columns = [];
2026
        rootFields.forEach((field) => {
2027
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2028
            ref.instance.field = field;
2029
            ref.changeDetectorRef.detectChanges();
2030
            columns.push(ref.instance);
2031
        });
2032
        return columns;
2033
    }
2034

2035
    protected generateFromData(fields: string[]) {
2036
        const separator = this.pivotKeys.columnDimensionSeparator;
2037
        const dataArr = fields.map(x => x.split(separator)).sort(x => x.length);
2038
        const hierarchy = new Map<string, any>();
2039
        dataArr.forEach(arr => {
2040
            let currentHierarchy = hierarchy;
2041
            const path = [];
2042
            for (const val of arr) {
2043
                path.push(val);
2044
                const newPath = path.join(separator);
2045
                let targetHierarchy = currentHierarchy.get(newPath);
2046
                if (!targetHierarchy) {
2047
                    currentHierarchy.set(newPath, { value: newPath, expandable: true, children: new Map<string, any>(), dimension: this.columnDimensions[0] });
2048
                    targetHierarchy = currentHierarchy.get(newPath);
2049
                }
2050
                currentHierarchy = targetHierarchy.children;
2051
            }
2052
        });
2053
        return hierarchy;
2054
    }
2055

2056
    protected generateColumnHierarchy(fields: Map<string, any>, data, parent = null): IgxColumnComponent[] {
2057
        let columns = [];
2058
        if (fields.size === 0) {
2059
            this.values.forEach((value) => {
2060
                const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2061
                ref.instance.header = value.displayName;
2062
                ref.instance.field = value.member;
2063
                ref.instance.parent = parent;
2064
                ref.instance.sortable = true;
2065
                ref.instance.dataType = value.dataType || this.resolveDataTypes(data[0][value.member]);
2066
                ref.instance.formatter = value.formatter;
2067
                columns.push(ref.instance);
2068
            });
2069
            return columns;
2070
        }
2071
        const currentFields = fields;
2072
        currentFields.forEach((value) => {
2073
            let shouldGenerate = true;
2074
            if (data.length === 0) {
2075
                shouldGenerate = false;
2076
            }
2077
            if (shouldGenerate && (value.children == null || value.children.length === 0 || value.children.size === 0)) {
2078
                const col = this.createColumnForDimension(value, data, parent, this.hasMultipleValues);
2079
                columns.push(col);
2080
                if (this.hasMultipleValues) {
2081
                    const measureChildren = this.getMeasureChildren(data, col, false, value.dimension.width);
2082
                    col.children.reset(measureChildren);
2083
                    columns = columns.concat(measureChildren);
2084
                }
2085

2086
            } else if (shouldGenerate) {
2087
                const col = this.createColumnForDimension(value, data, parent, true);
2088
                if (value.expandable) {
2089
                    col.headerTemplate = this.headerTemplate;
2090
                }
2091
                const children = this.generateColumnHierarchy(value.children, data, col);
2092
                const filteredChildren = children.filter(x => x.level === col.level + 1);
2093
                columns.push(col);
2094
                if (this.hasMultipleValues) {
2095
                    let measureChildren = this.getMeasureChildren(data, col, true, value.dimension.width);
2096
                    const nestedChildren = filteredChildren;
2097
                    //const allChildren = children.concat(measureChildren);
2098
                    col.children.reset(nestedChildren);
2099
                    columns = columns.concat(children);
2100
                    if (value.dimension.childLevel) {
2101
                        const sibling = this.createColumnForDimension(value, data, parent, true);
2102
                        columns.push(sibling);
2103

2104
                        measureChildren = this.getMeasureChildren(data, sibling, false, value.dimension?.width);
2105
                        sibling.children.reset(measureChildren);
2106
                        columns = columns.concat(measureChildren);
2107
                    }
2108

2109
                } else {
2110
                    col.children.reset(filteredChildren);
2111
                    columns = columns.concat(children);
2112
                    if (value.dimension.childLevel) {
2113
                        const sibling = this.createColumnForDimension(value, data, parent, false);
2114
                        columns.push(sibling);
2115
                    }
2116
                }
2117
            }
2118
        });
2119

2120
        return columns;
2121
    }
2122

2123
    protected createColumnForDimension(value: any, data: any, parent: ColumnType, isGroup: boolean) {
2124
        const key = value.value;
2125
        const ref = isGroup ?
2126
            createComponent(IgxColumnGroupComponent, { environmentInjector: this.envInjector, elementInjector: this.injector }) :
2127
            createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector });
2128
        ref.instance.header = parent != null ? key.split(parent.header + this.pivotKeys.columnDimensionSeparator)[1] : key;
2129
        ref.instance.field = key;
2130
        ref.instance.parent = parent;
2131
        if (value.dimension.width) {
2132
            ref.instance.width = value.dimension.width;
2133
        }
2134
        const valueDefinition = this.values[0];
2135
        ref.instance.dataType = valueDefinition?.dataType || this.resolveDataTypes(data[0][valueDefinition?.member]);
2136
        ref.instance.formatter = valueDefinition?.formatter;
2137
        ref.instance.sortable = true;
2138
        ref.changeDetectorRef.detectChanges();
2139
        return ref.instance;
2140
    }
2141

2142
    protected resolveColumnDimensionWidth(dim: IPivotDimension) {
2143
        if (dim.width) {
2144
            return dim.width;
2145
        }
2146
        return this.minColumnWidth + 'px';
2147
    }
2148

2149
    protected getMeasureChildren(data, parent, hidden, parentWidth) {
2150
        const cols = [];
2151
        const count = this.values.length;
2152
        const childWidth = parseInt(parentWidth, 10) / count;
2153
        const isPercent = parentWidth && parentWidth.indexOf('%') !== -1;
2154
        this.values.forEach(val => {
2155
            const ref = createComponent(IgxColumnComponent, { environmentInjector: this.envInjector, elementInjector: this.injector});
2156
            ref.instance.header = val.displayName || val.member;
2157
            ref.instance.field = parent.field + this.pivotKeys.columnDimensionSeparator + val.member;
2158
            ref.instance.parent = parent;
2159
            if (parentWidth) {
2160
                ref.instance.width = isPercent ? childWidth + '%' : childWidth + 'px';
2161
            }
2162
            ref.instance.hidden = hidden;
2163
            ref.instance.sortable = true;
2164
            ref.instance.dataType = val.dataType || this.resolveDataTypes(data[0][val.member]);
2165
            ref.instance.formatter = val.formatter;
2166
            ref.changeDetectorRef.detectChanges();
2167
            cols.push(ref.instance);
2168
        });
2169
        return cols;
2170
    }
2171

2172
    /**
2173
    * @hidden @internal
2174
    */
2175
    @ViewChild('emptyPivotGridTemplate', { read: TemplateRef, static: true })
2176
    public defaultEmptyPivotGridTemplate: TemplateRef<any>;
2177

2178
    /**
2179
     * Gets/Sets a custom template when pivot grid is empty.
2180
     *
2181
     * @example
2182
     * ```html
2183
     * <igx-pivot-grid [emptyPivotGridTemplate]="myTemplate"><igx-pivot-grid>
2184
     * ```
2185
     */
2186
    @Input()
2187
    public emptyPivotGridTemplate: TemplateRef<void>;
2188

2189
    /**
2190
    * @hidden @internal
2191
    */
2192
    public override get template(): TemplateRef<any> {
2193
        const allEnabledDimensions = this.rowDimensions.concat(this.columnDimensions);
2194
        if (allEnabledDimensions.length === 0 && this.values.length === 0) {
2195
            // no enabled values and dimensions
2196
            return this.emptyPivotGridTemplate || this.defaultEmptyPivotGridTemplate;
2197
        }
2198
        super.template;
2199
    }
2200

2201
    private emitInitEvents(pivotConfig: IPivotConfiguration) {
2202
        const dimensions = PivotUtil.flatten(this.allDimensions);
2203
        dimensions.forEach(dim => {
2204
            this.dimensionInit.emit(dim);
2205
        });
2206
        const values = pivotConfig?.values;
2207
        values?.forEach(val => {
2208
            this.valueInit.emit(val);
2209
        });
2210
    }
2211
}
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