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

IgniteUI / igniteui-angular / 16800667852

07 Aug 2025 09:31AM UTC coverage: 91.511% (+0.07%) from 91.44%
16800667852

Pull #16096

github

web-flow
Merge 4feeffc08 into 6d3657091
Pull Request #16096: Address grids column headers accessibility issues - active descendant, what is announced by SRs - master

13510 of 15839 branches covered (85.3%)

55 of 59 new or added lines in 9 files covered. (93.22%)

2 existing lines in 1 file now uncovered.

27240 of 29767 relevant lines covered (91.51%)

34666.81 hits per line

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

98.91
/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
import { GridColumnDataType } from '../../data-operations/data-util';
42

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

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

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

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

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

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

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

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

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

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

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

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

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

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

153
        return super.activeDescendant;
232✔
154
    }
155

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

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

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

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

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

225
    /**
226
    * @hidden
227
    * @internal
228
    */
229
    public override get isLeafHeaderAriaHidden(): boolean {
230
        return super.isLeafHeaderAriaHidden || this.grid.navigation.isRowHeaderActive || this.grid.navigation.isRowDimensionHeaderActive;
7,858✔
231
    }
232

233
    /**
234
    * @hidden
235
    * @internal
236
    */
237
    public calcHeight(col: ColumnType, index: number) {
238
        return !col.columnGroup && col.level < this.totalDepth && col.level === index ? (this.totalDepth - col.level) * this.grid.rowHeight : this.grid.rowHeight;
13,842✔
239
    }
240

241
    /**
242
    * @hidden
243
    * @internal
244
    */
245
    public isDuplicateOfExistingParent(col: ColumnType, lvl: number) {
246
        const parentCollection = lvl > 0 ? this.columnDimensionsByLevel[lvl - 1] : [];
15,140✔
247
        const duplicate = parentCollection.indexOf(col) !== -1;
15,140✔
248

249
        return duplicate;
15,140✔
250
    }
251

252
    /**
253
    * @hidden
254
    * @internal
255
    */
256
    public isMultiRow(col: ColumnType, lvl: number) {
257
        const isLeaf = !col.columnGroup;
15,140✔
258
        return isLeaf && lvl !== this.totalDepth - 1;
15,140✔
259
    }
260

261
    /**
262
    * @hidden
263
    * @internal
264
    */
265
    public populateColumnDimensionsByLevel() {
266
        const res = [];
1,167✔
267
        for (let i = 0; i < this.totalDepth; i++) {
1,167✔
268
            res[i] = [];
2,126✔
269
        }
270
        const cols = this.unpinnedColumnCollection;
1,167✔
271
        // populate column dimension matrix recursively
272
        this.populateDimensionRecursively(cols.filter(x => x.level === 0), 0, res);
12,131✔
273
        this.columnDimensionsByLevel = res;
1,167✔
274
    }
275

276
    protected populateDimensionRecursively(currentLevelColumns: ColumnType[], level = 0, res: any[]) {
×
277
        currentLevelColumns.forEach(col => {
5,089✔
278
            if (res[level]) {
12,119✔
279
                res[level].push(col);
12,074✔
280
                if (col.columnGroup && col.children.length > 0) {
12,074✔
281
                    const visibleColumns = col.children.toArray().filter(x => !x.hidden);
7,838✔
282
                    this.populateDimensionRecursively(visibleColumns, level + 1, res);
3,922✔
283
                } else if (level < this.totalDepth - 1) {
8,152✔
284
                    for (let i = level + 1; i <= this.totalDepth - 1; i++) {
137✔
285
                        res[i].push(col);
181✔
286
                    }
287
                }
288
            }
289
        });
290
    }
291

292
    /**
293
    * @hidden
294
    * @internal
295
    */
296
    public ngOnChanges(changes: SimpleChanges) {
297
        if (changes.unpinnedColumnCollection) {
2,179✔
298
            this.populateColumnDimensionsByLevel();
1,167✔
299
        }
300
    }
301

302
    /**
303
    * @hidden
304
    * @internal
305
    */
306
    public onDimDragStart(event, area) {
307
        this.cdr.detectChanges();
6✔
308
        for (const chip of this.notificationChips) {
6✔
309
            const parent = chip.nativeElement.parentElement;
18✔
310
            if (area.chipsList.toArray().indexOf(chip) === -1 &&
18✔
311
                parent.children.length > 0 &&
312
                parent.children.item(0).id !== 'empty') {
313
                chip.nativeElement.hidden = false;
7✔
314
                parent.parentElement.scrollTo({ left: chip.nativeElement.offsetLeft });
7✔
315
            }
316
        }
317
    }
318

319
    /**
320
    * @hidden
321
    * @internal
322
    */
323
    public onDimDragEnd() {
324
        for (const chip of this.notificationChips) {
5✔
325
            chip.nativeElement.hidden = true;
15✔
326
        }
327
    }
328

329
    /**
330
    * @hidden
331
    * @internal
332
    */
333
    public getAreaHeight(area: IgxChipsAreaComponent) {
334
        const chips = area.chipsList;
15,267✔
335
        return chips && chips.length > 0 ? chips.first.nativeElement.offsetHeight : 0;
15,267✔
336
    }
337

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

347
    /**
348
    * @hidden
349
    * @internal
350
    */
351
    public columnRemoved(event: IBaseChipEventArgs) {
352
        const col = this.grid.pivotConfiguration.columns.find(x => x.memberName === event.owner.id);
2✔
353
        this.grid.toggleDimension(col);
1✔
354
    }
355

356
    /**
357
    * @hidden
358
    * @internal
359
    */
360
    public valueRemoved(event: IBaseChipEventArgs) {
361
        const value = this.grid.pivotConfiguration.values.find(x => x.member === event.owner.id || x.displayName === event.owner.id);
3✔
362
        this.grid.toggleValue(value);
2✔
363
    }
364

365
    /**
366
    * @hidden
367
    * @internal
368
    */
369
    public filterRemoved(event: IBaseChipEventArgs) {
370
        const filter = this.grid.pivotConfiguration.filters.find(x => x.memberName === event.owner.id);
3✔
371
        this.grid.toggleDimension(filter);
2✔
372
        if (this.filterDropdownDimensions.size > 0) {
2✔
373
            this.onFiltersAreaDropdownClick({ target: this.filtersButton.el.nativeElement }, undefined, false);
1✔
374
        } else {
375
            this.grid.filteringService.hideESF();
1✔
376
        }
377
    }
378

379
    public onFiltersSelectionChanged(event?: IBaseChipEventArgs) {
380
        this.dropdownChips.chipsList.forEach(chip => {
1✔
381
            if (chip.id !== event.owner.id) {
2✔
382
                chip.selected = false
1✔
383
            }
384
        });
385
        this.onFiltersAreaDropdownClick({ target: this.filtersButton.el.nativeElement }, this.grid.filterDimensions.find(dim => dim.memberName === event.owner.id), false);
2✔
386
    }
387

388
    /**
389
    * @hidden
390
    * @internal
391
    */
392
    public onFilteringIconPointerDown(event) {
393
        event.stopPropagation();
1✔
394
        event.preventDefault();
1✔
395
    }
396

397
    /**
398
    * @hidden
399
    * @internal
400
    */
401
    public onFilteringIconClick(event, dimension) {
402
        event.stopPropagation();
5✔
403
        event.preventDefault();
5✔
404
        const dim = dimension;
5✔
405
        const col = this.grid.dimensionDataColumns.find(x => x.field === dim.memberName || x.field === dim.member);
8✔
406
        this.grid.filteringService.toggleFilterDropdown(event.target, col);
5✔
407
    }
408

409
    /**
410
    * @hidden
411
    * @internal
412
    */
413
    public onSummaryClick(eventArgs, value: IPivotValue, dropdown: IgxDropDownComponent, chip: IgxChipComponent) {
414
        this._subMenuOverlaySettings.target = eventArgs.currentTarget;
4✔
415
        this.updateDropDown(value, dropdown, chip);
4✔
416
    }
417

418
    /**
419
     * @hidden @internal
420
     */
421
    public onFiltersAreaDropdownClick(event, dimension?, shouldReattach = true) {
3✔
422
        const dim = dimension || this.filterDropdownDimensions.values().next().value;
5✔
423
        const col = this.grid.dimensionDataColumns.find(x => x.field === dim.memberName || x.field === dim.member);
17✔
424
        if (shouldReattach) {
5✔
425
            this.dropdownChips.chipsList.forEach(chip => {
3✔
426
                chip.selected = false
6✔
427
            });
428
            this.dropdownChips.chipsList.first.selected = true;
3✔
429
        }
430
        this.grid.filteringService.toggleFiltersESF(this.esf, event.target, col, shouldReattach);
5✔
431
    }
432

433
    /**
434
    * @hidden
435
    * @internal
436
    */
437
    public onAggregationChange(event: ISelectionEventArgs) {
438

439
        if (!this.isSelected(event.newSelection.value)) {
2✔
440
            this.value.aggregate = event.newSelection.value;
2✔
441
            const isSingleValue = this.grid.values.length === 1;
2✔
442

443
            PivotUtil.updateColumnTypeByAggregator(this.grid.columns, this.value, isSingleValue);
2✔
444

445
            this.grid.pipeTrigger++;
2✔
446
        }
447
    }
448

449
    /**
450
    * @hidden
451
    * @internal
452
    */
453
    public isSelected(val: IPivotAggregator) {
454
        return this.value.aggregate.key === val.key;
46✔
455
    }
456

457
    /**
458
    * @hidden
459
    * @internal
460
    */
461
    public onChipSort(_event, dimension: IPivotDimension) {
462
        if (dimension.sortable === undefined || dimension.sortable) {
12!
463
            const startDirection = dimension.sortDirection || SortingDirection.None;
12✔
464
            const direction = startDirection + 1 > SortingDirection.Desc ?
12✔
465
                SortingDirection.None : startDirection + 1;
466
            this.grid.sortDimension(dimension, direction);
12✔
467
        }
468
    }
469

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

488
        this._dropPos = event.originalEvent.offsetX > pos ? DropPosition.AfterDropTarget : DropPosition.BeforeDropTarget;
6✔
489
        if (this._dropPos === DropPosition.AfterDropTarget) {
6✔
490
            event.owner.nativeElement.previousElementSibling.style.visibility = 'hidden';
3✔
491
            event.owner.nativeElement.nextElementSibling.style.visibility = '';
3✔
492
        } else {
493
            event.owner.nativeElement.nextElementSibling.style.visibility = 'hidden';
3✔
494
            event.owner.nativeElement.previousElementSibling.style.visibility = '';
3✔
495
        }
496
    }
497

498
    /**
499
    * @hidden
500
    * @internal
501
    */
502
    public onDimDragLeave(event) {
503
        event.owner.nativeElement.previousElementSibling.style.visibility = 'hidden';
1✔
504
        event.owner.nativeElement.nextElementSibling.style.visibility = 'hidden';
1✔
505
        this._dropPos = DropPosition.AfterDropTarget;
1✔
506
    }
507

508
    /**
509
    * @hidden
510
    * @internal
511
    */
512
    public onAreaDragLeave(event, area) {
513
        const dataChips = area.chipsList.toArray().filter(x => this.notificationChips.toArray().indexOf(x) === -1);
15✔
514
        dataChips.forEach(element => {
6✔
515
            if (element.nativeElement.previousElementSibling) {
9✔
516
                element.nativeElement.previousElementSibling.style.visibility = 'hidden';
9✔
517
            }
518
            if (element.nativeElement.nextElementSibling) {
9✔
519
                element.nativeElement.nextElementSibling.style.visibility = 'hidden';
9✔
520
            }
521
        });
522
    }
523

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

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

580
    protected updateDropDown(value: IPivotValue, dropdown: IgxDropDownComponent, chip: IgxChipComponent) {
581
        this.value = value;
4✔
582
        dropdown.width = chip.nativeElement.clientWidth + 'px';
4✔
583
        this.aggregateList = PivotUtil.getAggregateList(value, this.grid);
4✔
584
        this.cdr.detectChanges();
4✔
585
        dropdown.open(this._subMenuOverlaySettings);
4✔
586
    }
587

588
    protected getRowDimensionColumn(dim: IPivotDimension): ColumnType {
589
        return this.grid.dimensionDataColumns ? this.grid.dimensionDataColumns.find((col) => col.field === dim.memberName) : null;
1,505!
590
    }
591
}
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