diff --git a/projects/igniteui-angular/src/lib/grids/grid/cell-merge.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/cell-merge.spec.ts index c053bbce81d..44d8b53f24c 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/cell-merge.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/cell-merge.spec.ts @@ -464,6 +464,206 @@ describe('IgxGrid - Cell merging #grid', () => { ]); }); + it('should interrupt merge sequence correctly when there are multiple overlapping merge groups affected.', async () => { + const col1 = grid.getColumnByName('ProductName'); + const col2 = grid.getColumnByName('Downloads'); + const col3 = grid.getColumnByName('Released'); + const col4 = grid.getColumnByName('ReleaseDate'); + + col1.merge = true; + col2.merge = true; + col3.merge = true; + col4.merge = true; + + fix.detectChanges(); + + const data = [ + { + Downloads: 1000, + ID: 1, + ProductName: 'Ignite UI for JavaScript', + ReleaseDate: fix.componentInstance.today, + Released: true + }, + { + Downloads: 1000, + ID: 2, + ProductName: 'Ignite UI for JavaScript', + ReleaseDate: fix.componentInstance.today, + Released: true + }, + { + Downloads: 1000, + ID: 3, + ProductName: 'Ignite UI for Angular', + ReleaseDate: fix.componentInstance.today, + Released: true + }, + { + Downloads: 1000, + ID: 4, + ProductName: 'Ignite UI for JavaScript', + ReleaseDate: fix.componentInstance.prevDay, + Released: true + }, + { + Downloads: 100, + ID: 5, + ProductName: 'Ignite UI for Angular', + ReleaseDate: fix.componentInstance.prevDay, + Released: true + }, + { + Downloads: 1000, + ID: 6, + ProductName: 'Ignite UI for Angular', + ReleaseDate: null, + Released: true + }, + { + Downloads: 0, + ID: 7, + ProductName: null, + ReleaseDate: fix.componentInstance.prevDay, + Released: true + }, + { + Downloads: 1000, + ID: 8, + ProductName: 'NetAdvantage', + ReleaseDate: fix.componentInstance.prevDay, + Released: true + }, + { + Downloads: 1000, + ID: 9, + ProductName: 'NetAdvantage', + ReleaseDate: null, + Released: true + } + ]; + fix.componentInstance.data = data; + fix.detectChanges(); + + const row1 = grid.rowList.toArray()[0]; + UIInteractions.simulateClickAndSelectEvent(row1.cells.toArray()[1].nativeElement); + await wait(1); + fix.detectChanges(); + + GridFunctions.verifyColumnMergedState(grid, col1, [ + { value: 'Ignite UI for JavaScript', span: 1 }, + { value: 'Ignite UI for JavaScript', span: 1 }, + { value: 'Ignite UI for Angular', span: 1 }, + { value: 'Ignite UI for JavaScript', span: 1 }, + { value: 'Ignite UI for Angular', span: 2 }, + { value: null, span: 1 }, + { value: 'NetAdvantage', span: 2 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col2, [ + { value: 1000, span: 1 }, + { value: 1000, span: 3 }, + { value: 100, span: 1 }, + { value: 1000, span: 1 }, + { value: 0, span: 1 }, + { value: 1000, span: 2 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col3, [ + { value: true, span: 1 }, + { value: true, span: 8 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col4, [ + { value: fix.componentInstance.today, span: 1 }, + { value: fix.componentInstance.today, span: 2 }, + { value: fix.componentInstance.prevDay, span: 2 }, + { value: null, span: 1 }, + { value: fix.componentInstance.prevDay, span: 2 }, + { value: null, span: 1 } + ]); + + const row2 = grid.rowList.toArray()[1]; + UIInteractions.simulateClickAndSelectEvent(row2.cells.toArray()[1].nativeElement); + await wait(1); + fix.detectChanges(); + + GridFunctions.verifyColumnMergedState(grid, col1, [ + { value: 'Ignite UI for JavaScript', span: 1 }, + { value: 'Ignite UI for JavaScript', span: 1 }, + { value: 'Ignite UI for Angular', span: 1 }, + { value: 'Ignite UI for JavaScript', span: 1 }, + { value: 'Ignite UI for Angular', span: 2 }, + { value: null, span: 1 }, + { value: 'NetAdvantage', span: 2 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col2, [ + { value: 1000, span: 1 }, + { value: 1000, span: 1 }, + { value: 1000, span: 2 }, + { value: 100, span: 1 }, + { value: 1000, span: 1 }, + { value: 0, span: 1 }, + { value: 1000, span: 2 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col3, [ + { value: true, span: 1 }, + { value: true, span: 1 }, + { value: true, span: 7 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col4, [ + { value: fix.componentInstance.today, span: 1 }, + { value: fix.componentInstance.today, span: 1 }, + { value: fix.componentInstance.today, span: 1 }, + { value: fix.componentInstance.prevDay, span: 2 }, + { value: null, span: 1 }, + { value: fix.componentInstance.prevDay, span: 2 }, + { value: null, span: 1 } + ]); + + const row3 = grid.rowList.toArray()[2]; + UIInteractions.simulateClickAndSelectEvent(row3.cells.toArray()[1].nativeElement); + await wait(1); + fix.detectChanges(); + + GridFunctions.verifyColumnMergedState(grid, col1, [ + { value: 'Ignite UI for JavaScript', span: 2 }, + { value: 'Ignite UI for Angular', span: 1 }, + { value: 'Ignite UI for JavaScript', span: 1 }, + { value: 'Ignite UI for Angular', span: 2 }, + { value: null, span: 1 }, + { value: 'NetAdvantage', span: 2 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col2, [ + { value: 1000, span: 2 }, + { value: 1000, span: 1 }, + { value: 1000, span: 1 }, + { value: 100, span: 1 }, + { value: 1000, span: 1 }, + { value: 0, span: 1 }, + { value: 1000, span: 2 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col3, [ + { value: true, span: 2 }, + { value: true, span: 1 }, + { value: true, span: 6 } + ]); + + GridFunctions.verifyColumnMergedState(grid, col4, [ + { value: fix.componentInstance.today, span: 2 }, + { value: fix.componentInstance.today, span: 1 }, + { value: fix.componentInstance.prevDay, span: 2 }, + { value: null, span: 1 }, + { value: fix.componentInstance.prevDay, span: 2 }, + { value: null, span: 1 } + ]); + }); + }); describe('Updating', () => { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts index b6c2091ff0b..b480ca661f9 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.pipes.ts @@ -129,34 +129,34 @@ export class IgxGridUnmergeActivePipe implements PipeTransform { // if nothing to update, return return collection; } - let result = cloneArray(collection) as any; + + // collect full range of data to unmerge + let startIndex; + let endIndex; uniqueRoots.forEach(x => { - const index = result.indexOf(x); + const index = collection.indexOf(x); + if (!startIndex) { + startIndex = index; + } else { + startIndex = Math.min(startIndex, index); + } const colKeys = [...x.cellMergeMeta.keys()]; const cols = colsToMerge.filter(col => colKeys.indexOf(col.field) !== -1); - let res = []; for (const col of cols) { - - let childData = x.cellMergeMeta.get(col.field).childRecords; + const childData = x.cellMergeMeta.get(col.field).childRecords; const childRecs = childData.map(rec => rec.recordRef); - const isDate = col?.dataType === 'date' || col?.dataType === 'dateTime'; - const isTime = col?.dataType === 'time' || col?.dataType === 'dateTime'; - res = this.grid.mergeStrategy.merge( - [x.recordRef, ...childRecs], - col.field, - col.mergingComparer, - res, - activeRowIndexes.map(ri => ri - index), - isDate, - isTime, - this.grid); - + if (!endIndex) { + endIndex = index + childRecs.length; + } else { + endIndex = Math.max(endIndex, index + childRecs.length + 1); + } } - result = result.slice(0, index).concat(res, result.slice(index + res.length)); }); - - - return result; + const dataToUnmerge = collection.slice(startIndex, endIndex).map(x => x.recordRef); + // unmerge data where active row index breaks merge groups + const res = DataUtil.merge(dataToUnmerge, colsToMerge, this.grid.mergeStrategy, activeRowIndexes.map(ri => ri - startIndex), this.grid); + collection = collection.slice(0, startIndex).concat(res, collection.slice(startIndex + res.length)); + return collection; } }