Skip to content

Commit

Permalink
[DataGrid] Better fix the scrollToIndexes logic (#1969)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari authored Jun 29, 2021
1 parent 5c11ab8 commit 2b0daf2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,33 +217,22 @@ export const useGridVirtualRows = (apiRef: GridApiRef): void => {
}
}

let isRowIndexAbove = false;
let isRowIndexBelow = false;

// Logic copied from https://www.w3.org/TR/wai-aria-practices/examples/listbox/js/listbox.js
if (params.rowIndex != null) {
const elementIndex = !options.pagination
? params.rowIndex
: params.rowIndex - paginationState.page * paginationState.pageSize;

const currentRowPage = elementIndex / gridState.containerSizes!.viewportPageSize;
const scrollPosition = currentRowPage * gridState!.viewportSizes.height;
const viewportHeight = gridState.viewportSizes.height;

isRowIndexAbove = windowRef.current!.scrollTop > scrollPosition;
isRowIndexBelow =
windowRef.current!.scrollTop + viewportHeight < scrollPosition + rowHeight;

if (isRowIndexAbove) {
scrollCoordinates.top = scrollPosition; // We put it at the top of the page
logger.debug(`Row is above, setting top to ${scrollCoordinates.top}`);
} else if (isRowIndexBelow) {
// We make sure the row is not half visible
scrollCoordinates.top = scrollPosition - viewportHeight + rowHeight;
logger.debug(`Row is below, setting top to ${scrollCoordinates.top}`);
const scrollBottom = windowRef.current!.clientHeight + windowRef.current!.scrollTop;
const elementBottom = rowHeight * elementIndex + rowHeight;
if (elementBottom > scrollBottom) {
scrollCoordinates.top = elementBottom - windowRef.current!.clientHeight;
} else if (rowHeight * elementIndex < windowRef.current!.scrollTop) {
scrollCoordinates.top = rowHeight * elementIndex;
}
}

const needScroll = !isColVisible || isRowIndexAbove || isRowIndexBelow;
const needScroll = !isColVisible || typeof scrollCoordinates.top !== undefined;
if (needScroll) {
apiRef.current.scroll(scrollCoordinates);
}
Expand Down
29 changes: 27 additions & 2 deletions packages/grid/x-grid/src/tests/rows.XGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -452,19 +452,44 @@ describe('<XGrid /> - Rows', () => {
it('should scroll correctly when the given index is partially visible at the bottom', () => {
const headerHeight = 40;
const rowHeight = 50;
const offset = 10;
const border = 1;
render(
<TestCaseVirtualization
hideFooter
headerHeight={headerHeight}
height={headerHeight + 4 * rowHeight + 10 + border * 2}
height={headerHeight + 4 * rowHeight + offset + border * 2}
nbCols={2}
rowHeight={rowHeight}
/>,
);
const gridWindow = document.querySelector('.MuiDataGrid-window')!;
apiRef.current.scrollToIndexes({ rowIndex: 4, colIndex: 0 });
expect(gridWindow.scrollTop).to.equal(rowHeight);
expect(gridWindow.scrollTop).to.equal(rowHeight - offset);
});

it('should scroll correctly when the given index is partially visible at the top', () => {
const headerHeight = 40;
const rowHeight = 50;
const offset = 10;
const border = 1;
render(
<TestCaseVirtualization
hideFooter
headerHeight={headerHeight}
height={headerHeight + 4 * rowHeight + border + border * 2}
nbCols={2}
rowHeight={rowHeight}
/>,
);
const gridWindow = document.querySelector('.MuiDataGrid-window')!;
gridWindow.scrollTop = offset;
apiRef.current.scrollToIndexes({ rowIndex: 2, colIndex: 0 });
expect(gridWindow.scrollTop).to.equal(offset);
apiRef.current.scrollToIndexes({ rowIndex: 1, colIndex: 0 });
expect(gridWindow.scrollTop).to.equal(offset);
apiRef.current.scrollToIndexes({ rowIndex: 0, colIndex: 0 });
expect(gridWindow.scrollTop).to.equal(0);
});
});
});
Expand Down

0 comments on commit 2b0daf2

Please sign in to comment.