From 567afecbf1549a017d3b7cdacbc4caad93fbd3ba Mon Sep 17 00:00:00 2001 From: IMinchev64 Date: Fri, 7 Jun 2024 10:33:38 +0300 Subject: [PATCH 1/3] feat(pivotGrid): row dimension expand/collapse with kb interaction --- .../pivot-grid-keyboard-nav.spec.ts | 520 ++++++++++-------- .../pivot-grid-navigation.service.ts | 37 +- 2 files changed, 327 insertions(+), 230 deletions(-) diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-keyboard-nav.spec.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-keyboard-nav.spec.ts index 1ce9cde05fc..4d73ef8cd31 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-keyboard-nav.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-keyboard-nav.spec.ts @@ -3,7 +3,7 @@ import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { GridFunctions } from '../../test-utils/grid-functions.spec'; -import { IgxPivotGridMultipleRowComponent } from '../../test-utils/pivot-grid-samples.spec'; +import { IgxPivotGridMultipleRowComponent, IgxPivotGridTestBaseComponent } from '../../test-utils/pivot-grid-samples.spec'; import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec'; import { IgxPivotGridComponent } from './pivot-grid.component'; import { IgxPivotRowDimensionHeaderComponent } from './pivot-row-dimension-header.component'; @@ -16,250 +16,312 @@ const HEADER_CELL_CSS_CLASS = '.igx-grid-th'; const ACTIVE_CELL_CSS_CLASS = '.igx-grid-th--active'; describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { + describe('General Keyboard Navigation', () => { + let fixture: ComponentFixture; + let pivotGrid: IgxPivotGridComponent; + configureTestSuite((() => { + return TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + IgxPivotGridMultipleRowComponent + ] + }); + })); + + beforeEach(fakeAsync(() => { + fixture = TestBed.createComponent(IgxPivotGridMultipleRowComponent); + fixture.detectChanges(); + pivotGrid = fixture.componentInstance.pivotGrid; + })); + + it('should allow navigating between row headers', () => { + const allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const firstCell = allGroups[0]; + const secondCell = allGroups.filter(x => x.componentInstance.column.field === 'Country')[0]; + UIInteractions.simulateClickAndSelectEvent(firstCell); + fixture.detectChanges(); + + GridFunctions.verifyHeaderIsFocused(firstCell.parent); + let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', firstCell.nativeElement); + fixture.detectChanges(); + GridFunctions.verifyHeaderIsFocused(secondCell.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + + // should do nothing if wrong key is pressed + UIInteractions.simulateClickAndSelectEvent(firstCell); + fixture.detectChanges(); + GridFunctions.verifyHeaderIsFocused(firstCell.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + UIInteractions.triggerKeyDownEvtUponElem('h', firstCell.nativeElement); + fixture.detectChanges(); + GridFunctions.verifyHeaderIsFocused(firstCell.parent); + }); + + it('should not go outside of the boundaries of the row dimensions content', () => { + const allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const firstCell = allGroups[0]; + const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; + UIInteractions.simulateClickAndSelectEvent(firstCell); + fixture.detectChanges(); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', firstCell.nativeElement); + fixture.detectChanges(); + + GridFunctions.verifyHeaderIsFocused(firstCell.parent); + let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); - let fixture: ComponentFixture; - let pivotGrid: IgxPivotGridComponent; - configureTestSuite((() => { - return TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - IgxPivotGridMultipleRowComponent - ] + UIInteractions.simulateClickAndSelectEvent(thirdCell); + fixture.detectChanges(); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', thirdCell.nativeElement); + fixture.detectChanges(); + + GridFunctions.verifyHeaderIsFocused(thirdCell.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); }); - })); - - beforeEach(fakeAsync(() => { - fixture = TestBed.createComponent(IgxPivotGridMultipleRowComponent); - fixture.detectChanges(); - pivotGrid = fixture.componentInstance.pivotGrid; - })); - - it('should allow navigating between row headers', () => { - const allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const firstCell = allGroups[0]; - const secondCell = allGroups.filter(x => x.componentInstance.column.field === 'Country')[0]; - UIInteractions.simulateClickAndSelectEvent(firstCell); - fixture.detectChanges(); - - GridFunctions.verifyHeaderIsFocused(firstCell.parent); - let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - - UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', firstCell.nativeElement); - fixture.detectChanges(); - GridFunctions.verifyHeaderIsFocused(secondCell.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - - // should do nothing if wrong key is pressed - UIInteractions.simulateClickAndSelectEvent(firstCell); - fixture.detectChanges(); - GridFunctions.verifyHeaderIsFocused(firstCell.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - UIInteractions.triggerKeyDownEvtUponElem('h', firstCell.nativeElement); - fixture.detectChanges(); - GridFunctions.verifyHeaderIsFocused(firstCell.parent); - }); - it('should not go outside of the boundaries of the row dimensions content', () => { - const allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const firstCell = allGroups[0]; - const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; - UIInteractions.simulateClickAndSelectEvent(firstCell); - fixture.detectChanges(); + it('should allow navigating from first to last row headers in a row(Home/End)', () => { + const allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const firstCell = allGroups[0]; + const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; + UIInteractions.simulateClickAndSelectEvent(firstCell); + fixture.detectChanges(); + + UIInteractions.triggerKeyDownEvtUponElem('End', firstCell.nativeElement); + fixture.detectChanges(); + GridFunctions.verifyHeaderIsFocused(thirdCell.parent); + let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + + UIInteractions.triggerKeyDownEvtUponElem('Home', thirdCell.nativeElement); + fixture.detectChanges(); + GridFunctions.verifyHeaderIsFocused(firstCell.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + }); - UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', firstCell.nativeElement); - fixture.detectChanges(); + it('should allow navigating from first to last row headers(Ctrl + ArrowDown)', () => { + let allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; + UIInteractions.simulateClickAndSelectEvent(thirdCell); + fixture.detectChanges(); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowDown', thirdCell.nativeElement, true, false, false, true); + fixture.detectChanges(); + + allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const lastCell = allGroups[allGroups.length - 1]; + GridFunctions.verifyHeaderIsFocused(lastCell.parent); + const activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + }); - GridFunctions.verifyHeaderIsFocused(firstCell.parent); - let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); + it('should allow navigating from any to first row headers(Ctrl + ArrowUp)', () => { + // Ctrl + arrowup + let allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[2] + UIInteractions.simulateClickAndSelectEvent(thirdCell); + fixture.detectChanges(); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', thirdCell.nativeElement, true, false, false, true); + fixture.detectChanges(); + + allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const firstCell = allGroups[0]; + GridFunctions.verifyHeaderIsFocused(firstCell.parent); + let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + + // just arrow up + UIInteractions.simulateClickAndSelectEvent(thirdCell); + fixture.detectChanges(); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', thirdCell.nativeElement, true, false, false, false); + fixture.detectChanges(); + allGroups = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + const secondCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[1]; + GridFunctions.verifyHeaderIsFocused(secondCell.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); - UIInteractions.simulateClickAndSelectEvent(thirdCell); - fixture.detectChanges(); + }); - UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', thirdCell.nativeElement); - fixture.detectChanges(); + it('should allow navigating between column headers', () => { + let firstHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + UIInteractions.simulateClickAndSelectEvent(firstHeader); + fixture.detectChanges(); + + firstHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + GridFunctions.verifyHeaderIsFocused(firstHeader.parent); + let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', pivotGrid.theadRow.nativeElement); + fixture.detectChanges(); + + const secondHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; + GridFunctions.verifyHeaderIsFocused(secondHeader.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + }); - GridFunctions.verifyHeaderIsFocused(thirdCell.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - }); + it('should allow navigating from first to last column headers', async () => { + let firstHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + UIInteractions.simulateClickAndSelectEvent(firstHeader); + fixture.detectChanges(); + + firstHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + + GridFunctions.verifyHeaderIsFocused(firstHeader.parent); + let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + + UIInteractions.triggerKeyDownEvtUponElem('End', pivotGrid.theadRow.nativeElement); + await wait(DEBOUNCE_TIME); + fixture.detectChanges(); + + const allHeaders = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`)); + const lastHeader = allHeaders[allHeaders.length - 1]; + GridFunctions.verifyHeaderIsFocused(lastHeader.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + }); - it('should allow navigating from first to last row headers in a row(Home/End)', () => { - const allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const firstCell = allGroups[0]; - const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; - UIInteractions.simulateClickAndSelectEvent(firstCell); - fixture.detectChanges(); - - UIInteractions.triggerKeyDownEvtUponElem('End', firstCell.nativeElement); - fixture.detectChanges(); - GridFunctions.verifyHeaderIsFocused(thirdCell.parent); - let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - - UIInteractions.triggerKeyDownEvtUponElem('Home', thirdCell.nativeElement); - fixture.detectChanges(); - GridFunctions.verifyHeaderIsFocused(firstCell.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - }); + it('should allow navigating in column headers when switching focus from rows to columns', () => { + const [firstCell] = fixture.debugElement.queryAll( + By.css(`${PIVOT_TBODY_CSS_CLASS} ${PIVOT_ROW_DIMENSION_CONTENT} ${HEADER_CELL_CSS_CLASS}`)); + UIInteractions.simulateClickAndSelectEvent(firstCell); + fixture.detectChanges(); + + let firstHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + UIInteractions.simulateClickAndSelectEvent(firstHeader); + fixture.detectChanges(); + + firstHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + GridFunctions.verifyHeaderIsFocused(firstHeader.parent); + let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + + UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', firstHeader.nativeElement); + fixture.detectChanges(); + const secondHeader = fixture.debugElement.queryAll( + By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; + GridFunctions.verifyHeaderIsFocused(secondHeader.parent); + activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); + expect(activeCells.length).toBe(1); + }); - it('should allow navigating from first to last row headers(Ctrl + ArrowDown)', () => { - let allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; - UIInteractions.simulateClickAndSelectEvent(thirdCell); - fixture.detectChanges(); - - UIInteractions.triggerKeyDownEvtUponElem('ArrowDown', thirdCell.nativeElement, true, false, false, true); - fixture.detectChanges(); - - allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const lastCell = allGroups[allGroups.length - 1]; - GridFunctions.verifyHeaderIsFocused(lastCell.parent); - const activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); + it('should allow navigating within the cells of the body', async () => { + const cell = pivotGrid.rowList.first.cells.first; + GridFunctions.focusFirstCell(fixture, pivotGrid); + fixture.detectChanges(); + expect(pivotGrid.navigation.activeNode.row).toBeUndefined(); + expect(pivotGrid.navigation.activeNode.column).toBeUndefined(); + + UIInteractions.simulateClickAndSelectEvent(cell.nativeElement); + fixture.detectChanges(); + + GridFunctions.focusFirstCell(fixture, pivotGrid); + fixture.detectChanges(); + expect(pivotGrid.navigation.activeNode.row).toBeDefined(); + expect(pivotGrid.navigation.activeNode.column).toBeDefined(); + + let activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`)); + expect(activeCells.length).toBe(1); + expect(cell.column.field).toEqual('Stanley-UnitsSold'); + + const gridContent = GridFunctions.getGridContent(fixture); + UIInteractions.triggerEventHandlerKeyDown('arrowright', gridContent); + await wait(30); + fixture.detectChanges(); + + activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`)); + expect(activeCells.length).toBe(1); + expect(activeCells[0].componentInstance.column.field).toEqual('Stanley-UnitPrice') + }); }); + describe('Row Dimension Expand/Collapse Keyboard Interactions', () => { + let fixture: ComponentFixture; + configureTestSuite((() => { + return TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + IgxPivotGridTestBaseComponent + ] + }); + })); - it('should allow navigating from any to first row headers(Ctrl + ArrowUp)', () => { - // Ctrl + arrowup - let allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[2] - UIInteractions.simulateClickAndSelectEvent(thirdCell); - fixture.detectChanges(); - - UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', thirdCell.nativeElement, true, false, false, true); - fixture.detectChanges(); - - allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const firstCell = allGroups[0]; - GridFunctions.verifyHeaderIsFocused(firstCell.parent); - let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - - // just arrow up - UIInteractions.simulateClickAndSelectEvent(thirdCell); - fixture.detectChanges(); - - UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', thirdCell.nativeElement, true, false, false, false); - fixture.detectChanges(); - allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const secondCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[1]; - GridFunctions.verifyHeaderIsFocused(secondCell.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); + beforeEach(fakeAsync(() => { + fixture = TestBed.createComponent(IgxPivotGridTestBaseComponent); + fixture.detectChanges(); + })); - }); + it('should allow row dimension expand(Alt + ArrowDown/ArrowRight) and collapse(Alt + ArrowUp/ArrowLeft)', async () => { + const rowDimension = fixture.debugElement.queryAll( + By.css(`.igx-grid__tbody-pivot-dimension`)); + let allHeaders = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); - it('should allow navigating between column headers', () => { - let firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; - UIInteractions.simulateClickAndSelectEvent(firstHeader); - fixture.detectChanges(); - - firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; - GridFunctions.verifyHeaderIsFocused(firstHeader.parent); - let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - - UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', pivotGrid.theadRow.nativeElement); - fixture.detectChanges(); - - const secondHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; - GridFunctions.verifyHeaderIsFocused(secondHeader.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - }); + expect(allHeaders.length).toBe(5, 'There should initially be 5 row dimension headers'); - it('should allow navigating from first to last column headers', async () => { - let firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; - UIInteractions.simulateClickAndSelectEvent(firstHeader); - fixture.detectChanges(); - - firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; - - GridFunctions.verifyHeaderIsFocused(firstHeader.parent); - let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - - UIInteractions.triggerKeyDownEvtUponElem('End', pivotGrid.theadRow.nativeElement); - await wait(DEBOUNCE_TIME); - fixture.detectChanges(); - - const allHeaders = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`)); - const lastHeader = allHeaders[allHeaders.length - 1]; - GridFunctions.verifyHeaderIsFocused(lastHeader.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - }); + UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); + UIInteractions.triggerEventHandlerKeyDown('ArrowUp', rowDimension[0], true); + fixture.detectChanges(); - it('should allow navigating in column headers when switching focus from rows to columns', () => { - const [firstCell] = fixture.debugElement.queryAll( - By.css(`${PIVOT_TBODY_CSS_CLASS} ${PIVOT_ROW_DIMENSION_CONTENT} ${HEADER_CELL_CSS_CLASS}`)); - UIInteractions.simulateClickAndSelectEvent(firstCell); - fixture.detectChanges(); - - let firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; - UIInteractions.simulateClickAndSelectEvent(firstHeader); - fixture.detectChanges(); - - firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; - GridFunctions.verifyHeaderIsFocused(firstHeader.parent); - let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - - UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', firstHeader.nativeElement); - fixture.detectChanges(); - const secondHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; - GridFunctions.verifyHeaderIsFocused(secondHeader.parent); - activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); - expect(activeCells.length).toBe(1); - }); + allHeaders = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + + expect(allHeaders.length).toBe(1, 'There should be only 1 row dimension header after collapse with Alt + ArrowUp'); + + UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); + UIInteractions.triggerEventHandlerKeyDown('ArrowDown', rowDimension[0], true); + fixture.detectChanges(); + + allHeaders = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); - it('should allow navigating within the cells of the body', async () => { - const cell = pivotGrid.rowList.first.cells.first; - GridFunctions.focusFirstCell(fixture, pivotGrid); - fixture.detectChanges(); - expect(pivotGrid.navigation.activeNode.row).toBeUndefined(); - expect(pivotGrid.navigation.activeNode.column).toBeUndefined(); - - UIInteractions.simulateClickAndSelectEvent(cell.nativeElement); - fixture.detectChanges(); - - GridFunctions.focusFirstCell(fixture, pivotGrid); - fixture.detectChanges(); - expect(pivotGrid.navigation.activeNode.row).toBeDefined(); - expect(pivotGrid.navigation.activeNode.column).toBeDefined(); - - let activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`)); - expect(activeCells.length).toBe(1); - expect(cell.column.field).toEqual('Stanley-UnitsSold'); - - const gridContent = GridFunctions.getGridContent(fixture); - UIInteractions.triggerEventHandlerKeyDown('arrowright', gridContent); - await wait(30); - fixture.detectChanges(); - - activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`)); - expect(activeCells.length).toBe(1); - expect(activeCells[0].componentInstance.column.field).toEqual('Stanley-UnitPrice') + expect(allHeaders.length).toBe(5, 'There should be 5 row dimension headers after expand with Alt + ArrowDown'); + + UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); + UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', rowDimension[0], true); + fixture.detectChanges(); + + allHeaders = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + + expect(allHeaders.length).toBe(1, 'There should be 1 row dimension header after collapse with Alt + ArrowLeft'); + + UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); + UIInteractions.triggerEventHandlerKeyDown('ArrowRight', rowDimension[0], true); + fixture.detectChanges(); + + allHeaders = fixture.debugElement.queryAll( + By.directive(IgxPivotRowDimensionHeaderComponent)); + + expect(allHeaders.length).toBe(5, 'There should be 5 row dimension headers after expand with Alt + ArrowRight'); + }); }); }); diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts index 3b1de50309f..153dc0fb74e 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts @@ -1,7 +1,8 @@ import { IgxGridNavigationService } from '../grid-navigation.service'; import { Injectable } from '@angular/core'; import { IgxPivotGridComponent } from './pivot-grid.component'; -import { HEADER_KEYS } from '../../core/utils'; +import { HEADER_KEYS, ROW_COLLAPSE_KEYS, ROW_EXPAND_KEYS } from '../../core/utils'; +import { PivotUtil } from './pivot-util'; @Injectable() export class IgxPivotGridNavigationService extends IgxGridNavigationService { @@ -32,6 +33,10 @@ export class IgxPivotGridNavigationService extends IgxGridNavigationService { layout: null } + if (event.altKey) { + this.handleAlt(key, event); + return; + } if ((key.includes('left') || key === 'home') && this.activeNode.column > 0) { newActiveNode.column = ctrl || key === 'home' ? 0 : this.activeNode.column - 1; } @@ -67,6 +72,36 @@ export class IgxPivotGridNavigationService extends IgxGridNavigationService { } } + public override handleAlt(key: string, event: KeyboardEvent): void { + event.preventDefault(); + + let row = this.grid.gridAPI.get_row_by_index(this.activeNode.row); + let expansionRowKey = PivotUtil.getRecordKey(row.data, row.data.dimensions[0]) + let isExpanded = this.grid.expansionStates.has(expansionRowKey) ? this.grid.expansionStates.get(expansionRowKey) : true; + console.log(isExpanded) + + if (!isExpanded && ROW_EXPAND_KEYS.has(key)) { + if (row.key === undefined) { + // TODO use expanded row.expanded = !row.expanded; + (row as any).toggle(); + } else { + const newExpansionState = new Map(this.grid.expansionStates); + newExpansionState.set(expansionRowKey, true); + this.grid.expansionStates = newExpansionState; + } + } else if (isExpanded && ROW_COLLAPSE_KEYS.has(key)) { + if (row.key === undefined) { + // TODO use expanded row.expanded = !row.expanded; + (row as any).toggle(); + } else { + const newExpansionState = new Map(this.grid.expansionStates); + newExpansionState.set(expansionRowKey, false); + this.grid.expansionStates = newExpansionState; + } + } + this.grid.notifyChanges(); + } + public override focusTbody(event) { if (!this.activeNode || this.activeNode.row === null || this.activeNode.row === undefined) { this.activeNode = this.lastActiveNode; From 2f3df66dc6cbb2578c3c140fc413e87dde1c1b8c Mon Sep 17 00:00:00 2001 From: IMinchev64 Date: Fri, 7 Jun 2024 15:25:06 +0300 Subject: [PATCH 2/3] chore(pivotGrid): remove redundant console.log() --- .../src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts index 153dc0fb74e..82c45878de4 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts @@ -78,7 +78,6 @@ export class IgxPivotGridNavigationService extends IgxGridNavigationService { let row = this.grid.gridAPI.get_row_by_index(this.activeNode.row); let expansionRowKey = PivotUtil.getRecordKey(row.data, row.data.dimensions[0]) let isExpanded = this.grid.expansionStates.has(expansionRowKey) ? this.grid.expansionStates.get(expansionRowKey) : true; - console.log(isExpanded) if (!isExpanded && ROW_EXPAND_KEYS.has(key)) { if (row.key === undefined) { From 06de3d2853c719995073773f8de5b6372d053b92 Mon Sep 17 00:00:00 2001 From: IMinchev64 Date: Mon, 17 Jun 2024 17:10:25 +0300 Subject: [PATCH 3/3] chore(pivotGrid): apply comments for navigation --- .../pivot-grid-navigation.service.ts | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts index 82c45878de4..1342a516f31 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid-navigation.service.ts @@ -75,28 +75,14 @@ export class IgxPivotGridNavigationService extends IgxGridNavigationService { public override handleAlt(key: string, event: KeyboardEvent): void { event.preventDefault(); - let row = this.grid.gridAPI.get_row_by_index(this.activeNode.row); - let expansionRowKey = PivotUtil.getRecordKey(row.data, row.data.dimensions[0]) - let isExpanded = this.grid.expansionStates.has(expansionRowKey) ? this.grid.expansionStates.get(expansionRowKey) : true; + const row = this.grid.gridAPI.get_row_by_index(this.activeNode.row); + const expansionRowKey = PivotUtil.getRecordKey(row.data, row.data.dimensions[this.activeNode.column]) + const isExpanded = this.grid.expansionStates.get(expansionRowKey) ?? true; - if (!isExpanded && ROW_EXPAND_KEYS.has(key)) { - if (row.key === undefined) { - // TODO use expanded row.expanded = !row.expanded; - (row as any).toggle(); - } else { - const newExpansionState = new Map(this.grid.expansionStates); - newExpansionState.set(expansionRowKey, true); - this.grid.expansionStates = newExpansionState; - } - } else if (isExpanded && ROW_COLLAPSE_KEYS.has(key)) { - if (row.key === undefined) { - // TODO use expanded row.expanded = !row.expanded; - (row as any).toggle(); - } else { - const newExpansionState = new Map(this.grid.expansionStates); - newExpansionState.set(expansionRowKey, false); - this.grid.expansionStates = newExpansionState; - } + if (ROW_EXPAND_KEYS.has(key) && !isExpanded) { + this.grid.gridAPI.set_row_expansion_state(expansionRowKey, true, event) + } else if (ROW_COLLAPSE_KEYS.has(key) && isExpanded) { + this.grid.gridAPI.set_row_expansion_state(expansionRowKey, false, event) } this.grid.notifyChanges(); }