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

IgniteUI / igniteui-angular / 15973272403

30 Jun 2025 12:45PM UTC coverage: 91.493% (+0.08%) from 91.415%
15973272403

Pull #15982

github

web-flow
Merge 64f9aeb1a into 8911970c8
Pull Request #15982: Address grids column headers accessibility issues - active descendant, what is announced by SRs

13452 of 15773 branches covered (85.28%)

33 of 34 new or added lines in 8 files covered. (97.06%)

150 existing lines in 3 files now uncovered.

27156 of 29681 relevant lines covered (91.49%)

39536.1 hits per line

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

98.9
/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.ts
1
import {
2
    ChangeDetectionStrategy,
3
    ChangeDetectorRef,
4
    Component,
5
    ElementRef,
6
    Inject,
7
    OnChanges,
8
    QueryList,
9
    Renderer2,
10
    ViewChild,
11
    SimpleChanges,
12
    ViewChildren,
13
    HostBinding
14
} from '@angular/core';
15
import { IBaseChipEventArgs, IgxChipComponent } from '../../chips/chip.component';
16
import { IgxChipsAreaComponent } from '../../chips/chips-area.component';
17
import { SortingDirection } from '../../data-operations/sorting-strategy';
18
import { IgxGridForOfDirective } from '../../directives/for-of/for_of.directive';
19
import { ISelectionEventArgs } from '../../drop-down/drop-down.common';
20
import { IgxDropDownComponent } from '../../drop-down/drop-down.component';
21
import { AbsoluteScrollStrategy, AutoPositionStrategy, OverlaySettings, PositionSettings, VerticalAlignment } from '../../services/public_api';
22
import { ColumnType, IGX_GRID_BASE, PivotGridType } from '../common/grid.interface';
23
import { IgxGridHeaderGroupComponent } from '../headers/grid-header-group.component';
24
import { IgxGridHeaderRowComponent } from '../headers/grid-header-row.component';
25
import { DropPosition } from '../moving/moving.service';
26
import { IPivotAggregator, IPivotDimension, IPivotValue, PivotDimensionType } from './pivot-grid.interface';
27
import { PivotUtil } from './pivot-util';
28
import { IgxGridTopLevelColumns } from '../common/pipes';
29
import { IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe } from '../headers/pipes';
30
import { IgxExcelStyleSearchComponent } from '../filtering/excel-style/excel-style-search.component';
31
import { IgxGridExcelStyleFilteringComponent, IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleFilterOperationsTemplateDirective } from '../filtering/excel-style/excel-style-filtering.component';
32
import { IgxDropDownItemComponent } from '../../drop-down/drop-down-item.component';
33
import { IgxDropDownItemNavigationDirective } from '../../drop-down/drop-down-navigation.directive';
34
import { IgxSuffixDirective } from '../../directives/suffix/suffix.directive';
35
import { IgxBadgeComponent } from '../../badge/badge.component';
36
import { IgxPrefixDirective } from '../../directives/prefix/prefix.directive';
37
import { IgxIconComponent } from '../../icon/icon.component';
38
import { IgxDropDirective } from '../../directives/drag-drop/drag-drop.directive';
39
import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common';
40
import { IgxPivotRowHeaderGroupComponent } from './pivot-row-header-group.component';
41

42
/**
43
 *
44
 * For all intents & purposes treat this component as what a <thead> usually is in the default <table> element.
45
 *
46
 * This container holds the pivot grid header elements and their behavior/interactions.
47
 *
48
 * @hidden @internal
49
 */
50
@Component({
51
    changeDetection: ChangeDetectionStrategy.OnPush,
52
    selector: 'igx-pivot-header-row',
53
    templateUrl: './pivot-header-row.component.html',
54
    imports: [IgxDropDirective, IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent,
55
        IgxPrefixDirective, IgxBadgeComponent, IgxSuffixDirective, IgxDropDownItemNavigationDirective,
56
        NgTemplateOutlet, IgxGridHeaderGroupComponent, NgClass, NgStyle, IgxGridForOfDirective,
57
        IgxDropDownComponent, IgxDropDownItemComponent, IgxGridExcelStyleFilteringComponent,
58
        IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleFilterOperationsTemplateDirective,
59
        IgxExcelStyleSearchComponent, IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe, IgxGridTopLevelColumns,
60
        IgxPivotRowHeaderGroupComponent]
61
})
62
export class IgxPivotHeaderRowComponent extends IgxGridHeaderRowComponent implements OnChanges {
3✔
63
    public aggregateList: IPivotAggregator[] = [];
133✔
64

65
    public value: IPivotValue;
66
    public filterDropdownDimensions: Set<any> = new Set<any>();
133✔
67
    public filterAreaDimensions: Set<any> = new Set<any>();
133✔
68
    private _dropPos = DropPosition.AfterDropTarget;
133✔
69
    private _subMenuPositionSettings: PositionSettings = {
133✔
70
        verticalStartPoint: VerticalAlignment.Bottom,
71
        closeAnimation: undefined
72
    };
73
    private _subMenuOverlaySettings: OverlaySettings = {
133✔
74
        closeOnOutsideClick: true,
75
        modal: false,
76
        positionStrategy: new AutoPositionStrategy(this._subMenuPositionSettings),
77
        scrollStrategy: new AbsoluteScrollStrategy()
78
    };
79

80
    /**
81
     * @hidden @internal
82
     */
83
    @ViewChild('esf') public esf: any;
84

85
    /**
86
     * @hidden @internal
87
     */
88
    @ViewChild('filterAreaHidden', { static: false }) public filterArea;
89

90
    /**
91
     * @hidden @internal
92
     */
93
    @ViewChild('filterIcon') public filtersButton;
94

95
    /**
96
     * @hidden @internal
97
     */
98
    @ViewChild('dropdownChips') public dropdownChips;
99

100
    /**
101
     * @hidden @internal
102
     */
103
    @ViewChild('pivotFilterContainer') public pivotFilterContainer;
104

105
    /**
106
     * @hidden @internal
107
     */
108
    @ViewChild('pivotRowContainer') public pivotRowContainer;
109

110
    /**
111
    * @hidden
112
    * @internal
113
    */
114
    @ViewChildren('notifyChip')
115
    public notificationChips: QueryList<IgxChipComponent>;
116

117
    /**
118
    * @hidden
119
    * @internal
120
    * The virtualized part of the header row containing the unpinned header groups.
121
    */
122
    @ViewChildren('headerVirtualContainer', { read: IgxGridForOfDirective })
123
    public headerContainers: QueryList<IgxGridForOfDirective<ColumnType, ColumnType[]>>;
124

125
    /**
126
    * @hidden
127
    * @internal
128
    */
129
    @ViewChildren('rowDimensionHeaders')
130
    public rowDimensionHeaders: QueryList<IgxPivotRowHeaderGroupComponent>;
131

132
    public override get headerForOf() {
133
        return this.headerContainers?.last;
426✔
134
    }
135

136
    @HostBinding('attr.aria-activedescendant')
137
    public override get activeDescendant(): string {
138
        const activeElem = this.navigation.activeNode;
4,332✔
139
        if (!activeElem || !Object.keys(activeElem).length || this.grid.navigation.headerRowActiveDescendant) {
4,332✔
140
            return null;
4,090✔
141
        }
142

143
        if (this.navigation.isRowDimensionHeaderActive) {
242✔
144
            const activeHeader = this.grid.theadRow.rowDimensionHeaders.find(h => h.active);
12✔
145
            if (activeHeader) {
10✔
146
                const key = activeHeader.title ?? activeHeader.rootDimension?.memberName;
10✔
147
                return key ? `${this.grid.id}_${key}` : null;
10!
148
            }
NEW
149
            return null;
×
150
        }
151

152
        return super.activeDescendant;
232✔
153
    }
154

155
    constructor(
156
        @Inject(IGX_GRID_BASE) public override grid: PivotGridType,
133✔
157
        ref: ElementRef<HTMLElement>,
158
        cdr: ChangeDetectorRef,
159
        protected renderer: Renderer2
133✔
160
    ) {
161
        super(ref, cdr);
133✔
162
    }
163

164
    /**
165
    * @hidden
166
    * @internal
167
    * Default is a single empty level since default depth is 1
168
    */
169
    public columnDimensionsByLevel: any[] = [[]];
133✔
170

171
    /**
172
    * @hidden @internal
173
    */
174
    public get isFiltersButton(): boolean {
175
        let chipsWidth = 0;
2,163✔
176
        this.filterDropdownDimensions.clear();
2,163✔
177
        this.filterAreaDimensions.clear();
2,163✔
178
        if (this.filterArea?.chipsList && this.filterArea.chipsList.length !== 0) {
2,163✔
179
            const styles = getComputedStyle(this.pivotFilterContainer.nativeElement);
121✔
180
            const containerPaddings = parseFloat(styles.paddingLeft) + parseFloat(styles.paddingRight);
121✔
181
            chipsWidth += containerPaddings + (this.filtersButton && this.filterArea?.chipsList.length > 1 ? this.filtersButton.el.nativeElement.getBoundingClientRect().width : 0);
121✔
182
            this.filterArea.chipsList.forEach(chip => {
121✔
183
                const dim = this.grid.filterDimensions.find(x => x.memberName === chip.id);
241✔
184
                if (dim) {
179✔
185
                    // 8 px margin between chips
186
                    const currentChipWidth = chip.nativeElement.getBoundingClientRect().width + 8;
173✔
187
                    if (chipsWidth + currentChipWidth < this.grid.pivotRowWidths) {
173✔
188
                        this.filterAreaDimensions.add(dim);
75✔
189
                    } else {
190
                        this.filterDropdownDimensions.add(dim);
98✔
191
                    }
192
                    chipsWidth += currentChipWidth;
173✔
193
                }
194
            });
195
            return this.filterDropdownDimensions.size > 0;
121✔
196
        }
197
        return false;
2,042✔
198
    }
199

200
    /**
201
    * @hidden
202
    * @internal
203
    */
204
    public get totalDepth() {
205
        const columnDimensions = this.grid.columnDimensions;
59,603✔
206
        if (columnDimensions.length === 0) {
59,603✔
207
            return 1;
966✔
208
        }
209
        let totalDepth = columnDimensions.map(x => this.grid.data?.length > 0 ? PivotUtil.getDimensionDepth(x) + 1 : 0).reduce((acc, val) => acc + val);
61,875✔
210
        if (this.grid.hasMultipleValues) {
58,637✔
211
            totalDepth += 1;
54,599✔
212
        }
213
        return totalDepth;
58,637✔
214
    }
215

216
    /**
217
    * @hidden
218
    * @internal
219
    */
220
    public get maxContainerHeight() {
221
        return this.totalDepth * this.grid.renderedRowHeight;
2,163✔
222
    }
223

224
    /**
225
    * @hidden
226
    * @internal
227
    */
228
    public calcHeight(col: ColumnType, index: number) {
229
        return !col.columnGroup && col.level < this.totalDepth && col.level === index ? (this.totalDepth - col.level) * this.grid.rowHeight : this.grid.rowHeight;
13,756✔
230
    }
231

232
    /**
233
    * @hidden
234
    * @internal
235
    */
236
    public isDuplicateOfExistingParent(col: ColumnType, lvl: number) {
237
        const parentCollection = lvl > 0 ? this.columnDimensionsByLevel[lvl - 1] : [];
15,054✔
238
        const duplicate = parentCollection.indexOf(col) !== -1;
15,054✔
239

240
        return duplicate;
15,054✔
241
    }
242

243
    /**
244
    * @hidden
245
    * @internal
246
    */
247
    public isMultiRow(col: ColumnType, lvl: number) {
248
        const isLeaf = !col.columnGroup;
15,054✔
249
        return isLeaf && lvl !== this.totalDepth - 1;
15,054✔
250
    }
251

252
    /**
253
    * @hidden
254
    * @internal
255
    */
256
    public populateColumnDimensionsByLevel() {
257
        const res = [];
1,159✔
258
        for (let i = 0; i < this.totalDepth; i++) {
1,159✔
259
            res[i] = [];
2,110✔
260
        }
261
        const cols = this.unpinnedColumnCollection;
1,159✔
262
        // populate column dimension matrix recursively
263
        this.populateDimensionRecursively(cols.filter(x => x.level === 0), 0, res);
12,011✔
264
        this.columnDimensionsByLevel = res;
1,159✔
265
    }
266

267
    protected populateDimensionRecursively(currentLevelColumns: ColumnType[], level = 0, res: any[]) {
×
268
        currentLevelColumns.forEach(col => {
5,041✔
269
            if (res[level]) {
11,999✔
270
                res[level].push(col);
11,954✔
271
                if (col.columnGroup && col.children.length > 0) {
11,954✔
272
                    const visibleColumns = col.children.toArray().filter(x => !x.hidden);
7,758✔
273
                    this.populateDimensionRecursively(visibleColumns, level + 1, res);
3,882✔
274
                } else if (level < this.totalDepth - 1) {
8,072✔
275
                    for (let i = level + 1; i <= this.totalDepth - 1; i++) {
137✔
276
                        res[i].push(col);
181✔
277
                    }
278
                }
279
            }
280
        });
281
    }
282

283
    /**
284
    * @hidden
285
    * @internal
286
    */
287
    public ngOnChanges(changes: SimpleChanges) {
288
        if (changes.unpinnedColumnCollection) {
2,166✔
289
            this.populateColumnDimensionsByLevel();
1,159✔
290
        }
291
    }
292

293
    /**
294
    * @hidden
295
    * @internal
296
    */
297
    public onDimDragStart(event, area) {
298
        this.cdr.detectChanges();
6✔
299
        for (const chip of this.notificationChips) {
6✔
300
            const parent = chip.nativeElement.parentElement;
18✔
301
            if (area.chipsList.toArray().indexOf(chip) === -1 &&
18✔
302
                parent.children.length > 0 &&
303
                parent.children.item(0).id !== 'empty') {
304
                chip.nativeElement.hidden = false;
7✔
305
                parent.parentElement.scrollTo({ left: chip.nativeElement.offsetLeft });
7✔
306
            }
307
        }
308
    }
309

310
    /**
311
    * @hidden
312
    * @internal
313
    */
314
    public onDimDragEnd() {
315
        for (const chip of this.notificationChips) {
5✔
316
            chip.nativeElement.hidden = true;
15✔
317
        }
318
    }
319

320
    /**
321
    * @hidden
322
    * @internal
323
    */
324
    public getAreaHeight(area: IgxChipsAreaComponent) {
325
        const chips = area.chipsList;
15,163✔
326
        return chips && chips.length > 0 ? chips.first.nativeElement.offsetHeight : 0;
15,163✔
327
    }
328

329
    /**
330
    * @hidden
331
    * @internal
332
    */
333
    public rowRemoved(event: IBaseChipEventArgs) {
334
        const row = this.grid.pivotConfiguration.rows.find(x => x.memberName === event.owner.id);
2✔
335
        this.grid.toggleDimension(row);
1✔
336
    }
337

338
    /**
339
    * @hidden
340
    * @internal
341
    */
342
    public columnRemoved(event: IBaseChipEventArgs) {
343
        const col = this.grid.pivotConfiguration.columns.find(x => x.memberName === event.owner.id);
2✔
344
        this.grid.toggleDimension(col);
1✔
345
    }
346

347
    /**
348
    * @hidden
349
    * @internal
350
    */
351
    public valueRemoved(event: IBaseChipEventArgs) {
352
        const value = this.grid.pivotConfiguration.values.find(x => x.member === event.owner.id || x.displayName === event.owner.id);
3✔
353
        this.grid.toggleValue(value);
2✔
354
    }
355

356
    /**
357
    * @hidden
358
    * @internal
359
    */
360
    public filterRemoved(event: IBaseChipEventArgs) {
361
        const filter = this.grid.pivotConfiguration.filters.find(x => x.memberName === event.owner.id);
3✔
362
        this.grid.toggleDimension(filter);
2✔
363
        if (this.filterDropdownDimensions.size > 0) {
2✔
364
            this.onFiltersAreaDropdownClick({ target: this.filtersButton.el.nativeElement }, undefined, false);
1✔
365
        } else {
366
            this.grid.filteringService.hideESF();
1✔
367
        }
368
    }
369

370
    public onFiltersSelectionChanged(event?: IBaseChipEventArgs) {
371
        this.dropdownChips.chipsList.forEach(chip => {
1✔
372
            if (chip.id !== event.owner.id) {
2✔
373
                chip.selected = false
1✔
374
            }
375
        });
376
        this.onFiltersAreaDropdownClick({ target: this.filtersButton.el.nativeElement }, this.grid.filterDimensions.find(dim => dim.memberName === event.owner.id), false);
2✔
377
    }
378

379
    /**
380
    * @hidden
381
    * @internal
382
    */
383
    public onFilteringIconPointerDown(event) {
384
        event.stopPropagation();
1✔
385
        event.preventDefault();
1✔
386
    }
387

388
    /**
389
    * @hidden
390
    * @internal
391
    */
392
    public onFilteringIconClick(event, dimension) {
393
        event.stopPropagation();
5✔
394
        event.preventDefault();
5✔
395
        const dim = dimension;
5✔
396
        const col = this.grid.dimensionDataColumns.find(x => x.field === dim.memberName || x.field === dim.member);
8✔
397
        this.grid.filteringService.toggleFilterDropdown(event.target, col);
5✔
398
    }
399

400
    /**
401
    * @hidden
402
    * @internal
403
    */
404
    public onSummaryClick(eventArgs, value: IPivotValue, dropdown: IgxDropDownComponent, chip: IgxChipComponent) {
405
        this._subMenuOverlaySettings.target = eventArgs.currentTarget;
4✔
406
        this.updateDropDown(value, dropdown, chip);
4✔
407
    }
408

409
    /**
410
     * @hidden @internal
411
     */
412
    public onFiltersAreaDropdownClick(event, dimension?, shouldReattach = true) {
3✔
413
        const dim = dimension || this.filterDropdownDimensions.values().next().value;
5✔
414
        const col = this.grid.dimensionDataColumns.find(x => x.field === dim.memberName || x.field === dim.member);
17✔
415
        if (shouldReattach) {
5✔
416
            this.dropdownChips.chipsList.forEach(chip => {
3✔
417
                chip.selected = false
6✔
418
            });
419
            this.dropdownChips.chipsList.first.selected = true;
3✔
420
        }
421
        this.grid.filteringService.toggleFiltersESF(this.esf, event.target, col, shouldReattach);
5✔
422
    }
423

424
    /**
425
    * @hidden
426
    * @internal
427
    */
428
    public onAggregationChange(event: ISelectionEventArgs) {
429

430
        if (!this.isSelected(event.newSelection.value)) {
2✔
431
            this.value.aggregate = event.newSelection.value;
2✔
432
            const isSingleValue = this.grid.values.length === 1;
2✔
433

434
            PivotUtil.updateColumnTypeByAggregator(this.grid.columns, this.value, isSingleValue);
2✔
435

436
            this.grid.pipeTrigger++;
2✔
437
        }
438
    }
439

440
    /**
441
    * @hidden
442
    * @internal
443
    */
444
    public isSelected(val: IPivotAggregator) {
445
        return this.value.aggregate.key === val.key;
46✔
446
    }
447

448
    /**
449
    * @hidden
450
    * @internal
451
    */
452
    public onChipSort(_event, dimension: IPivotDimension) {
453
        if (dimension.sortable === undefined || dimension.sortable) {
12!
454
            const startDirection = dimension.sortDirection || SortingDirection.None;
12✔
455
            const direction = startDirection + 1 > SortingDirection.Desc ?
12✔
456
                SortingDirection.None : startDirection + 1;
457
            this.grid.sortDimension(dimension, direction);
12✔
458
        }
459
    }
460

461
    /**
462
    * @hidden
463
    * @internal
464
    */
465
    public onDimDragOver(event, dimension?: PivotDimensionType) {
466
        if (!event.dragChip || !event.dragChip.data?.pivotArea) return;
7!
467
        const typeMismatch = dimension !== undefined ? this.grid.pivotConfiguration.values.find(x => x.member === event.dragChip.id
9✔
468
            || x.displayName === event.dragChip.id) :
469
            !this.grid.pivotConfiguration.values.find(x => x.member === event.dragChip.id || x.displayName === event.dragChip.id);
3✔
470
        if (typeMismatch) {
7✔
471
            // cannot drag between dimensions and value
472
            return;
1✔
473
        }
474
        // if we are in the left half of the chip, drop on the left
475
        // else drop on the right of the chip
476
        const clientRect = event.owner.nativeElement.getBoundingClientRect();
6✔
477
        const pos = clientRect.width / 2;
6✔
478

479
        this._dropPos = event.originalEvent.offsetX > pos ? DropPosition.AfterDropTarget : DropPosition.BeforeDropTarget;
6✔
480
        if (this._dropPos === DropPosition.AfterDropTarget) {
6✔
481
            event.owner.nativeElement.previousElementSibling.style.visibility = 'hidden';
3✔
482
            event.owner.nativeElement.nextElementSibling.style.visibility = '';
3✔
483
        } else {
484
            event.owner.nativeElement.nextElementSibling.style.visibility = 'hidden';
3✔
485
            event.owner.nativeElement.previousElementSibling.style.visibility = '';
3✔
486
        }
487
    }
488

489
    /**
490
    * @hidden
491
    * @internal
492
    */
493
    public onDimDragLeave(event) {
494
        event.owner.nativeElement.previousElementSibling.style.visibility = 'hidden';
1✔
495
        event.owner.nativeElement.nextElementSibling.style.visibility = 'hidden';
1✔
496
        this._dropPos = DropPosition.AfterDropTarget;
1✔
497
    }
498

499
    /**
500
    * @hidden
501
    * @internal
502
    */
503
    public onAreaDragLeave(event, area) {
504
        const dataChips = area.chipsList.toArray().filter(x => this.notificationChips.toArray().indexOf(x) === -1);
15✔
505
        dataChips.forEach(element => {
6✔
506
            if (element.nativeElement.previousElementSibling) {
9✔
507
                element.nativeElement.previousElementSibling.style.visibility = 'hidden';
9✔
508
            }
509
            if (element.nativeElement.nextElementSibling) {
9✔
510
                element.nativeElement.nextElementSibling.style.visibility = 'hidden';
9✔
511
            }
512
        });
513
    }
514

515
    /**
516
    * @hidden
517
    * @internal
518
    */
519
    public onValueDrop(event, area) {
520
        if (!(event.dragChip && event.dragChip.data?.pivotArea) && !(event.dragData?.chip && !!event.dragData.chip.data.pivotArea)) return;
2!
521
        //values can only be reordered
522
        const values = this.grid.pivotConfiguration.values;
2✔
523
        const dragId = event.dragChip?.id || event.dragData?.chip.id;
2!
524
        const chipsArray = area.chipsList.toArray();
2✔
525
        let chipIndex = chipsArray.indexOf(event.owner) !== -1 ? chipsArray.indexOf(event.owner) : chipsArray.length;
2!
526
        chipIndex = this._dropPos === DropPosition.AfterDropTarget ? chipIndex + 1 : chipIndex;
2✔
527
        const value = values.find(x => x.member === dragId || x.displayName === dragId);
3✔
528
        if (value) {
2✔
529
            const dragChipIndex = chipsArray.indexOf(event.dragChip || event.dragData.chip);
2!
530
            this.grid.moveValue(value, dragChipIndex >= chipIndex ? chipIndex : chipIndex - 1);
2✔
531
        }
532
    }
533

534
    /**
535
    * @hidden
536
    * @internal
537
    */
538
    public onDimDrop(event, area, dimensionType: PivotDimensionType) {
539
        if (!(event.dragChip && event.dragChip.data?.pivotArea) && !(event.dragData?.chip && !!event.dragData.chip.data.pivotArea)) return;
5!
540
        const dragId = event.dragChip?.id || event.dragData?.chip.id;
5!
541
        const currentDim = this.grid.getDimensionsByType(dimensionType);
5✔
542
        const chipsArray = area.chipsList.toArray();
5✔
543
        const chip = chipsArray.find(x => x.id === dragId);
7✔
544
        const isNewChip = chip === undefined;
5✔
545
        const isReorder = event.owner.id !== undefined;
5✔
546
        //const chipIndex = chipsArray.indexOf(event.owner) !== -1 ? chipsArray.indexOf(event.owner) : chipsArray.length;
547
        const chipIndex = currentDim.findIndex(x => x.memberName === event.owner.id) !== -1 ?
6✔
548
            currentDim.findIndex(x => x.memberName === event.owner.id) : currentDim.length;
5✔
549
        const targetIndex = this._dropPos === DropPosition.AfterDropTarget ? chipIndex + 1 : chipIndex;
5✔
550
        if (isNewChip) {
5✔
551
            // chip moved from an external collection
552
            const dim = this.grid.allDimensions.find(x => x && x.memberName === dragId);
7✔
553
            if (!dim) {
3!
554
                // you have dragged something that is not a dimension
555
                return;
×
556
            }
557
            this.grid.moveDimension(dim, dimensionType, targetIndex);
3✔
558
        } else if (isReorder) {
2✔
559
            // chip from same collection, reordered.
560
            const newDim = currentDim.find(x => x.memberName === dragId);
2✔
561
            const dragChipIndex = currentDim.findIndex(x => x.memberName === dragId);
2✔
562
            this.grid.moveDimension(newDim, dimensionType, dragChipIndex > chipIndex ? targetIndex : targetIndex - 1);
2!
563
        }
564
        this.grid.pipeTrigger++;
5✔
565
        this.grid.dimensionsChange.emit({ dimensions: currentDim, dimensionCollectionType: dimensionType });
5✔
566
        // clean states
567
        this.onDimDragEnd();
5✔
568
        this.onAreaDragLeave(event, area);
5✔
569
    }
570

571
    protected updateDropDown(value: IPivotValue, dropdown: IgxDropDownComponent, chip: IgxChipComponent) {
572
        this.value = value;
4✔
573
        dropdown.width = chip.nativeElement.clientWidth + 'px';
4✔
574
        this.aggregateList = PivotUtil.getAggregateList(value, this.grid);
4✔
575
        this.cdr.detectChanges();
4✔
576
        dropdown.open(this._subMenuOverlaySettings);
4✔
577
    }
578

579
    protected getRowDimensionColumn(dim: IPivotDimension): ColumnType {
580
        return this.grid.dimensionDataColumns ? this.grid.dimensionDataColumns.find((col) => col.field === dim.memberName) : null;
1,505!
581
    }
582
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc