Skip to content

Commit f9f6b60

Browse files
authored
Merge pull request #16362 from IgniteUI/mkirova/fix-unmerge-pipe
fix(igxGrid): Fix unmerge when merge groups partially overlap.
2 parents d4d9738 + d27416e commit f9f6b60

File tree

2 files changed

+235
-20
lines changed

2 files changed

+235
-20
lines changed

projects/igniteui-angular/src/lib/grids/grid/cell-merge.spec.ts

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,10 @@ describe('IgxGrid - Cell merging #grid', () => {
472472

473473
UIInteractions.simulateClickAndSelectEvent(row1.cells.toArray()[1].nativeElement);
474474
await wait(1);
475+
(grid as any)._activeRowIndexes = null;
475476
fix.detectChanges();
476477

478+
expect((grid as any).activeRowIndexes).toEqual([0, 0]);
477479
GridFunctions.verifyColumnMergedState(grid, col, [
478480
{ value: 'Ignite UI for JavaScript', span: 1 },
479481
{ value: 'Ignite UI for JavaScript', span: 1 },
@@ -485,6 +487,212 @@ describe('IgxGrid - Cell merging #grid', () => {
485487
]);
486488
});
487489

490+
it('should interrupt merge sequence correctly when there are multiple overlapping merge groups affected.', async () => {
491+
const col1 = grid.getColumnByName('ProductName');
492+
const col2 = grid.getColumnByName('Downloads');
493+
const col3 = grid.getColumnByName('Released');
494+
const col4 = grid.getColumnByName('ReleaseDate');
495+
496+
col1.merge = true;
497+
col2.merge = true;
498+
col3.merge = true;
499+
col4.merge = true;
500+
501+
fix.detectChanges();
502+
503+
const data = [
504+
{
505+
Downloads: 1000,
506+
ID: 1,
507+
ProductName: 'Ignite UI for JavaScript',
508+
ReleaseDate: fix.componentInstance.today,
509+
Released: true
510+
},
511+
{
512+
Downloads: 1000,
513+
ID: 2,
514+
ProductName: 'Ignite UI for JavaScript',
515+
ReleaseDate: fix.componentInstance.today,
516+
Released: true
517+
},
518+
{
519+
Downloads: 1000,
520+
ID: 3,
521+
ProductName: 'Ignite UI for Angular',
522+
ReleaseDate: fix.componentInstance.today,
523+
Released: true
524+
},
525+
{
526+
Downloads: 1000,
527+
ID: 4,
528+
ProductName: 'Ignite UI for JavaScript',
529+
ReleaseDate: fix.componentInstance.prevDay,
530+
Released: true
531+
},
532+
{
533+
Downloads: 100,
534+
ID: 5,
535+
ProductName: 'Ignite UI for Angular',
536+
ReleaseDate: fix.componentInstance.prevDay,
537+
Released: true
538+
},
539+
{
540+
Downloads: 1000,
541+
ID: 6,
542+
ProductName: 'Ignite UI for Angular',
543+
ReleaseDate: null,
544+
Released: true
545+
},
546+
{
547+
Downloads: 0,
548+
ID: 7,
549+
ProductName: null,
550+
ReleaseDate: fix.componentInstance.prevDay,
551+
Released: true
552+
},
553+
{
554+
Downloads: 1000,
555+
ID: 8,
556+
ProductName: 'NetAdvantage',
557+
ReleaseDate: fix.componentInstance.prevDay,
558+
Released: true
559+
},
560+
{
561+
Downloads: 1000,
562+
ID: 9,
563+
ProductName: 'NetAdvantage',
564+
ReleaseDate: null,
565+
Released: true
566+
}
567+
];
568+
fix.componentInstance.data = data;
569+
fix.detectChanges();
570+
571+
const row1 = grid.rowList.toArray()[0];
572+
UIInteractions.simulateClickAndSelectEvent(row1.cells.toArray()[1].nativeElement);
573+
await wait(1);
574+
(grid as any)._activeRowIndexes = null;
575+
fix.detectChanges();
576+
577+
expect((grid as any).activeRowIndexes).toEqual([0, 0]);
578+
GridFunctions.verifyColumnMergedState(grid, col1, [
579+
{ value: 'Ignite UI for JavaScript', span: 1 },
580+
{ value: 'Ignite UI for JavaScript', span: 1 },
581+
{ value: 'Ignite UI for Angular', span: 1 },
582+
{ value: 'Ignite UI for JavaScript', span: 1 },
583+
{ value: 'Ignite UI for Angular', span: 2 },
584+
{ value: null, span: 1 },
585+
{ value: 'NetAdvantage', span: 2 }
586+
]);
587+
588+
GridFunctions.verifyColumnMergedState(grid, col2, [
589+
{ value: 1000, span: 1 },
590+
{ value: 1000, span: 3 },
591+
{ value: 100, span: 1 },
592+
{ value: 1000, span: 1 },
593+
{ value: 0, span: 1 },
594+
{ value: 1000, span: 2 }
595+
]);
596+
597+
GridFunctions.verifyColumnMergedState(grid, col3, [
598+
{ value: true, span: 1 },
599+
{ value: true, span: 8 }
600+
]);
601+
602+
GridFunctions.verifyColumnMergedState(grid, col4, [
603+
{ value: fix.componentInstance.today, span: 1 },
604+
{ value: fix.componentInstance.today, span: 2 },
605+
{ value: fix.componentInstance.prevDay, span: 2 },
606+
{ value: null, span: 1 },
607+
{ value: fix.componentInstance.prevDay, span: 2 },
608+
{ value: null, span: 1 }
609+
]);
610+
611+
const row2 = grid.rowList.toArray()[1];
612+
UIInteractions.simulateClickAndSelectEvent(row2.cells.toArray()[1].nativeElement);
613+
await wait(1);
614+
(grid as any)._activeRowIndexes = null;
615+
fix.detectChanges();
616+
617+
expect((grid as any).activeRowIndexes).toEqual([1, 1]);
618+
GridFunctions.verifyColumnMergedState(grid, col1, [
619+
{ value: 'Ignite UI for JavaScript', span: 1 },
620+
{ value: 'Ignite UI for JavaScript', span: 1 },
621+
{ value: 'Ignite UI for Angular', span: 1 },
622+
{ value: 'Ignite UI for JavaScript', span: 1 },
623+
{ value: 'Ignite UI for Angular', span: 2 },
624+
{ value: null, span: 1 },
625+
{ value: 'NetAdvantage', span: 2 }
626+
]);
627+
628+
GridFunctions.verifyColumnMergedState(grid, col2, [
629+
{ value: 1000, span: 1 },
630+
{ value: 1000, span: 1 },
631+
{ value: 1000, span: 2 },
632+
{ value: 100, span: 1 },
633+
{ value: 1000, span: 1 },
634+
{ value: 0, span: 1 },
635+
{ value: 1000, span: 2 }
636+
]);
637+
638+
GridFunctions.verifyColumnMergedState(grid, col3, [
639+
{ value: true, span: 1 },
640+
{ value: true, span: 1 },
641+
{ value: true, span: 7 }
642+
]);
643+
644+
GridFunctions.verifyColumnMergedState(grid, col4, [
645+
{ value: fix.componentInstance.today, span: 1 },
646+
{ value: fix.componentInstance.today, span: 1 },
647+
{ value: fix.componentInstance.today, span: 1 },
648+
{ value: fix.componentInstance.prevDay, span: 2 },
649+
{ value: null, span: 1 },
650+
{ value: fix.componentInstance.prevDay, span: 2 },
651+
{ value: null, span: 1 }
652+
]);
653+
654+
const row3 = grid.rowList.toArray()[2];
655+
UIInteractions.simulateClickAndSelectEvent(row3.cells.toArray()[1].nativeElement);
656+
await wait(1);
657+
(grid as any)._activeRowIndexes = null;
658+
fix.detectChanges();
659+
660+
expect((grid as any).activeRowIndexes).toEqual([2, 2]);
661+
GridFunctions.verifyColumnMergedState(grid, col1, [
662+
{ value: 'Ignite UI for JavaScript', span: 2 },
663+
{ value: 'Ignite UI for Angular', span: 1 },
664+
{ value: 'Ignite UI for JavaScript', span: 1 },
665+
{ value: 'Ignite UI for Angular', span: 2 },
666+
{ value: null, span: 1 },
667+
{ value: 'NetAdvantage', span: 2 }
668+
]);
669+
670+
GridFunctions.verifyColumnMergedState(grid, col2, [
671+
{ value: 1000, span: 2 },
672+
{ value: 1000, span: 1 },
673+
{ value: 1000, span: 1 },
674+
{ value: 100, span: 1 },
675+
{ value: 1000, span: 1 },
676+
{ value: 0, span: 1 },
677+
{ value: 1000, span: 2 }
678+
]);
679+
680+
GridFunctions.verifyColumnMergedState(grid, col3, [
681+
{ value: true, span: 2 },
682+
{ value: true, span: 1 },
683+
{ value: true, span: 6 }
684+
]);
685+
686+
GridFunctions.verifyColumnMergedState(grid, col4, [
687+
{ value: fix.componentInstance.today, span: 2 },
688+
{ value: fix.componentInstance.today, span: 1 },
689+
{ value: fix.componentInstance.prevDay, span: 2 },
690+
{ value: null, span: 1 },
691+
{ value: fix.componentInstance.prevDay, span: 2 },
692+
{ value: null, span: 1 }
693+
]);
694+
});
695+
488696
});
489697

490698
describe('Updating', () => {

projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { FilterUtil, IFilteringStrategy } from '../../data-operations/filtering-
1010
import { ISortingExpression } from '../../data-operations/sorting-strategy';
1111
import { IGridSortingStrategy, IGridGroupingStrategy } from '../common/strategy';
1212
import { GridCellMergeMode, RowPinningPosition } from '../common/enums';
13-
import { IGridMergeStrategy } from '../../data-operations/merge-strategy';
13+
import { IGridMergeStrategy, IMergeByResult } from '../../data-operations/merge-strategy';
1414

1515
/**
1616
* @hidden
@@ -129,33 +129,40 @@ export class IgxGridUnmergeActivePipe implements PipeTransform {
129129
// if nothing to update, return
130130
return collection;
131131
}
132+
132133
let result = cloneArray(collection) as any;
133134
uniqueRoots.forEach(x => {
134-
const index = result.indexOf(x);
135+
const index = collection.indexOf(x);
135136
const colKeys = [...x.cellMergeMeta.keys()];
136137
const cols = colsToMerge.filter(col => colKeys.indexOf(col.field) !== -1);
137-
let res = [];
138138
for (const col of cols) {
139-
140-
let childData = x.cellMergeMeta.get(col.field).childRecords;
139+
const childData = x.cellMergeMeta.get(col.field).childRecords;
141140
const childRecs = childData.map(rec => rec.recordRef);
142-
const isDate = col?.dataType === 'date' || col?.dataType === 'dateTime';
143-
const isTime = col?.dataType === 'time' || col?.dataType === 'dateTime';
144-
res = this.grid.mergeStrategy.merge(
145-
[x.recordRef, ...childRecs],
146-
col.field,
147-
col.mergingComparer,
148-
res,
149-
activeRowIndexes.map(ri => ri - index),
150-
isDate,
151-
isTime,
152-
this.grid);
153-
141+
if(childRecs.length === 0) {
142+
// nothing to unmerge
143+
continue;
144+
}
145+
const unmergedData = DataUtil.merge([x.recordRef, ...childRecs], [col], this.grid.mergeStrategy, activeRowIndexes.map(ri => ri - index), this.grid);
146+
for (let i = 0; i < unmergedData.length; i++) {
147+
const unmergedRec = unmergedData[i];
148+
const origRecord = result[index + i];
149+
if (unmergedRec.cellMergeMeta?.get(col.field)) {
150+
// clone of object, since we don't want to pollute the original fully merged collection.
151+
const objCopy = {
152+
recordRef: origRecord.recordRef,
153+
ghostRecord: origRecord.ghostRecord,
154+
cellMergeMeta: new Map<string, IMergeByResult>(origRecord.cellMergeMeta.entries())
155+
};
156+
// update copy with new meta from unmerged data record, but just for this column
157+
objCopy.cellMergeMeta?.set(col.field, unmergedRec.cellMergeMeta.get(col.field));
158+
result[index + i] = objCopy;
159+
} else {
160+
// this is the unmerged record, with no merge metadata
161+
result[index + i] = unmergedRec;
162+
}
163+
}
154164
}
155-
result = result.slice(0, index).concat(res, result.slice(index + res.length));
156165
});
157-
158-
159166
return result;
160167
}
161168
}

0 commit comments

Comments
 (0)