Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Fix rendering issues #1319

Merged
merged 12 commits into from
Mar 31, 2021
6 changes: 5 additions & 1 deletion packages/grid/_modules_/grid/components/GridPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export const GridPagination = React.forwardRef<
const classes = useStyles();
const apiRef = React.useContext(GridApiContext);
const paginationState = useGridSelector(apiRef, gridPaginationSelector);
const lastPage = React.useMemo(
() => Math.floor(paginationState.rowCount / (paginationState.pageSize || 1)),
[paginationState.rowCount, paginationState.pageSize],
);
const options = useGridSelector(apiRef, optionsSelector);

const onPageSizeChange = React.useCallback(
Expand Down Expand Up @@ -80,7 +84,7 @@ export const GridPagination = React.forwardRef<
}}
component="div"
count={paginationState.rowCount}
page={paginationState.page}
page={paginationState.page <= lastPage ? paginationState.page : lastPage}
rowsPerPageOptions={
options.rowsPerPageOptions &&
options.rowsPerPageOptions.indexOf(paginationState.pageSize) > -1
Expand Down
6 changes: 5 additions & 1 deletion packages/grid/_modules_/grid/components/cell/GridCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ export const GridCell: React.FC<GridCellProps> = React.memo((props) => {
};

React.useLayoutEffect(() => {
if (hasFocus && cellMode === 'view' && cellRef.current) {
if (
hasFocus &&
cellRef.current &&
(!document.activeElement || !cellRef.current!.contains(document.activeElement))
) {
cellRef.current!.focus();
}
});
dtassone marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ export const useGridKeyboardNavigation = (
nextCellIndexes.colIndex = nextCellIndexes.colIndex <= 0 ? 0 : nextCellIndexes.colIndex;
nextCellIndexes.colIndex =
nextCellIndexes.colIndex >= colCount ? colCount - 1 : nextCellIndexes.colIndex;

apiRef.current.scrollToIndexes(nextCellIndexes);
dtassone marked this conversation as resolved.
Show resolved Hide resolved
apiRef.current.setCellFocus(nextCellIndexes);
},
[
Expand All @@ -137,8 +139,6 @@ export const useGridKeyboardNavigation = (

const setCellFocus = React.useCallback(
(nextCellIndexes: GridCellIndexCoordinates) => {
apiRef.current.scrollToIndexes(nextCellIndexes);

setGridState((state) => {
logger.debug(
`Focusing on cell with rowIndex=${nextCellIndexes.rowIndex} and colIndex=${nextCellIndexes.colIndex}`,
Expand All @@ -147,7 +147,7 @@ export const useGridKeyboardNavigation = (
});
forceUpdate();
},
[apiRef, forceUpdate, logger, setGridState],
[forceUpdate, logger, setGridState],
);

const handleCellFocus = React.useCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export const gridRowsLookupSelector = createSelector<
InternalGridRowsState,
GridRowsLookup
>(gridRowsStateSelector, (rows: InternalGridRowsState) => rows && rows.idRowsLookup);
export const unorderedGridRowIdsSelector = createSelector<
GridState,
InternalGridRowsState,
GridRowId[]
>(gridRowsStateSelector, (rows: InternalGridRowsState) => rows.allRows);
export const unorderedGridRowModelsSelector = createSelector<
GridState,
InternalGridRowsState,
Expand Down
14 changes: 12 additions & 2 deletions packages/grid/_modules_/grid/hooks/features/rows/useGridRows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,21 @@ export const useGridRows = (
}, [getRowIdProp, rows, setGridState]);

const getRowIndexFromId = React.useCallback(
(id: GridRowId): number => apiRef.current.state.rows.allRows.indexOf(id),
(id: GridRowId): number => {
if (apiRef.current.getSortedRowIds) {
return apiRef.current.getSortedRowIds().indexOf(id);
}
return apiRef.current.state.rows.allRows.indexOf(id);
},
[apiRef],
);
const getRowIdFromRowIndex = React.useCallback(
(index: number): GridRowId => apiRef.current.state.rows.allRows[index],
(index: number): GridRowId => {
if (apiRef.current.getSortedRowIds) {
return apiRef.current.getSortedRowIds()[index];
}
return apiRef.current.state.rows.allRows[index];
},
[apiRef],
);
const getRowFromId = React.useCallback(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@ import { GridState } from '../core/gridState';
import {
GridRowsLookup,
gridRowsLookupSelector,
unorderedGridRowIdsSelector,
unorderedGridRowModelsSelector,
} from '../rows/gridRowsSelector';
import { GridSortingState } from './gridSortingState';

const sortingGridStateSelector = (state: GridState) => state.sorting;
export const sortedGridRowIdsSelector = createSelector<GridState, GridSortingState, GridRowId[]>(
export const sortedGridRowIdsSelector = createSelector<
GridState,
GridSortingState,
GridRowId[],
GridRowId[]
>(
sortingGridStateSelector,
(sortingState: GridSortingState) => {
return sortingState.sortedRows;
unorderedGridRowIdsSelector,
(sortingState: GridSortingState, allRows: GridRowId[]) => {
return sortingState.sortedRows.length ? sortingState.sortedRows : allRows;
},
);
export const sortedGridRowsSelector = createSelector<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { GridFeatureModeConstant } from '../../../models/gridFeatureMode';
import { GridCellParams } from '../../../models/params/gridCellParams';
import { GridColParams } from '../../../models/params/gridColParams';
import { GridSortModelParams } from '../../../models/params/gridSortModelParams';
import { GridRowModel, GridRowsProp } from '../../../models/gridRows';
import { GridRowId, GridRowModel, GridRowsProp } from '../../../models/gridRows';
import {
GridFieldComparatorList,
GridSortItem,
Expand All @@ -33,6 +33,7 @@ import { allGridColumnsSelector, visibleGridColumnsSelector } from '../columns/g
import { useGridSelector } from '../core/useGridSelector';
import { useGridState } from '../core/useGridState';
import { gridRowCountSelector } from '../rows/gridRowsSelector';
import { sortedGridRowIdsSelector, sortedGridRowsSelector } from './gridSortingSelector';

export const useGridSorting = (apiRef: GridApiRef, rowsProp: GridRowsProp) => {
const logger = useLogger('useGridSorting');
Expand Down Expand Up @@ -225,6 +226,16 @@ export const useGridSorting = (apiRef: GridApiRef, rowsProp: GridRowsProp) => {
gridState.sorting.sortModel,
]);

const getSortedRows = React.useCallback(
(): GridRowModel[] => sortedGridRowsSelector(apiRef.current.state),
[apiRef],
);

const getSortedRowIds = React.useCallback(
(): GridRowId[] => sortedGridRowIdsSelector(apiRef.current.state),
[apiRef],
);

const onMultipleKeyPressed = React.useCallback(
(isPressed: boolean) => {
allowMultipleSorting.current = !options.disableMultipleColumnsSorting && isPressed;
Expand Down Expand Up @@ -270,6 +281,8 @@ export const useGridSorting = (apiRef: GridApiRef, rowsProp: GridRowsProp) => {

const sortApi: GridSortApi = {
getSortModel,
getSortedRows,
getSortedRowIds,
setSortModel,
sortColumn,
onSortModelChange,
Expand Down
18 changes: 5 additions & 13 deletions packages/grid/_modules_/grid/hooks/root/useGridContainerProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,11 @@ export const useGridContainerProps = (

const getVirtualRowCount = React.useCallback(() => {
logger.debug('Calculating virtual row count.');
const currentPage = paginationState.page;
let pageRowCount =
options.pagination && paginationState.pageSize ? paginationState.pageSize : null;

pageRowCount =
!pageRowCount || currentPage * pageRowCount <= visibleRowsCount
? pageRowCount
: visibleRowsCount - (currentPage - 1) * pageRowCount;

const virtRowsCount =
pageRowCount == null || pageRowCount > visibleRowsCount ? visibleRowsCount : pageRowCount;

return virtRowsCount;
if (options.pagination) {
const rowsLeft = visibleRowsCount - paginationState.page * paginationState.pageSize;
return rowsLeft > paginationState.pageSize ? paginationState.pageSize : rowsLeft;
}
return visibleRowsCount;
}, [
logger,
options.pagination,
Expand Down
4 changes: 4 additions & 0 deletions packages/grid/_modules_/grid/models/api/gridSortApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { GridColDef } from '../colDef/gridColDef';
import { GridRowId, GridRowModel } from '../gridRows';
import { GridSortDirection, GridSortModel } from '../gridSortModel';
import { GridSortModelParams } from '../params/gridSortModelParams';

Expand Down Expand Up @@ -30,4 +31,7 @@ export interface GridSortApi {
* @param direction
*/
sortColumn: (column: GridColDef, direction?: GridSortDirection) => void;

getSortedRows: () => GridRowModel[];
getSortedRowIds: () => GridRowId[];
}
23 changes: 23 additions & 0 deletions packages/grid/x-grid/src/tests/events.XGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
createClientRenderStrictMode,
// @ts-ignore
fireEvent,
// @ts-ignore
screen,
} from 'test/utils';
import { expect } from 'chai';
import {
Expand Down Expand Up @@ -142,7 +144,28 @@ describe('<XGrid /> - Events Params', () => {
api: apiRef.current,
});
});
it('should include the correct params when grid is sorted', () => {
dtassone marked this conversation as resolved.
Show resolved Hide resolved
const header = screen
.getByRole('columnheader', { name: 'first' })
.querySelector('.MuiDataGrid-colCellTitleContainer');
fireEvent.click(header);

const cell01 = getCell(0, 1);
fireEvent.click(cell01);

expect(eventArgs!.params).to.deep.include({
id: 2,
value: 'Jack',
formattedValue: 'Jack',
isEditable: true,
element: cell01,
row: baselineProps.rows[1],
rowIndex: 0,
colDef: apiRef!.current.getColumnFromField('first'),
colIndex: 1,
api: apiRef.current,
});
});
dtassone marked this conversation as resolved.
Show resolved Hide resolved
it('should consider value getter', () => {
const cellFirstAge = getCell(1, 3);
fireEvent.click(cellFirstAge);
Expand Down
35 changes: 35 additions & 0 deletions packages/grid/x-grid/src/tests/rows.XGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,5 +342,40 @@ describe('<XGrid /> - Rows', () => {
const isVirtualized = apiRef!.current!.getState().containerSizes!.isVirtualized;
expect(isVirtualized).to.equal(false);
});

describe('Pagination', () => {
dtassone marked this conversation as resolved.
Show resolved Hide resolved
it('should render only the pageSize ', () => {
dtassone marked this conversation as resolved.
Show resolved Hide resolved
render(<TestCaseVirtualization pagination pageSize={32} />);
const gridWindow = document.querySelector('.MuiDataGrid-window')!;
gridWindow.scrollTop = 10e6; // scroll to the bottom
gridWindow.dispatchEvent(new Event('scroll'));

const lastCell = document.querySelector(
'[role="row"]:last-child [role="cell"]:first-child',
)!;
expect(lastCell.textContent).to.equal('31');
const totalHeight = apiRef!.current!.getState().containerSizes?.totalSizes.height!;
dtassone marked this conversation as resolved.
Show resolved Hide resolved
expect(gridWindow.scrollHeight).to.equal(totalHeight);
});

it('should not virtualized the last page if smaller than viewport ', () => {
dtassone marked this conversation as resolved.
Show resolved Hide resolved
render(<TestCaseVirtualization pagination pageSize={32} page={3} height={500} />);
const gridWindow = document.querySelector('.MuiDataGrid-window')!;
gridWindow.scrollTop = 10e6; // scroll to the bottom
gridWindow.dispatchEvent(new Event('scroll'));

const lastCell = document.querySelector(
'[role="row"]:last-child [role="cell"]:first-child',
)!;
expect(lastCell.textContent).to.equal('99');
expect(gridWindow.scrollTop).to.equal(0);
expect(gridWindow.scrollHeight).to.equal(gridWindow.clientHeight);

const isVirtualized = apiRef!.current!.getState().containerSizes!.isVirtualized;
expect(isVirtualized).to.equal(false);
const virtualRowsCount = apiRef!.current!.getState().containerSizes!.virtualRowsCount;
expect(virtualRowsCount).to.equal(4);
});
});
});
});
2 changes: 1 addition & 1 deletion packages/storybook/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const parameters = {
// due to its circular structure
actions: {
argTypesRegex:
'^on((?!CellClick|CellDoubleClick|CellEditBlur|CellKeyDown|CellEnter|CellLeave|CellMouseDown|CellOut|CellOver|ColumnHeaderClick|ColumnHeaderDoubleClick|ColumnHeaderOver|ColumnHeaderOut|ColumnHeaderEnter|ColumnHeaderLeave|StateChange|RowClick|RowDoubleClick|RowEnter|RowLeave|RowOut|RowOver).)*$',
'^on((?!CellBlur|CellClick|CellDoubleClick|CellEditBlur|CellKeyDown|CellEnter|CellLeave|CellMouseDown|CellOut|CellOver|ColumnHeaderClick|ColumnHeaderDoubleClick|ColumnHeaderOver|ColumnHeaderOut|ColumnHeaderEnter|ColumnHeaderLeave|StateChange|RowClick|RowDoubleClick|RowEnter|RowLeave|RowOut|RowOver).)*$',
},
options: {
/**
Expand Down
5 changes: 3 additions & 2 deletions packages/storybook/src/stories/grid-rows.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
GRID_CELL_EDIT_EXIT,
GridEditCellPropsParams,
GridEditRowModelParams,
GRID_CELL_EDIT_ENTER,
} from '@material-ui/x-grid';
import { useDemoData } from '@material-ui/x-grid-data-generator';
import { action } from '@storybook/addon-actions';
Expand Down Expand Up @@ -806,7 +807,7 @@ export function EditCellWithCellClickGrid() {
(params: GridCellParams, event) => {
// Or you can use the editRowModel prop, but I find it easier
// apiRef.current.setCellMode(params.id, params.field, 'edit');
apiRef.current.publishEvent('cellEnterEdit', params, event);
apiRef.current.publishEvent(GRID_CELL_EDIT_ENTER, params, event);

// if I want to prevent selection I can do
event.stopPropagation();
Expand All @@ -829,7 +830,7 @@ export function EditCellWithMessageGrid() {

React.useEffect(() => {
return apiRef.current.subscribeEvent(
'cellEnterEdit',
GRID_CELL_EDIT_ENTER,
(param: GridCellParams, event?: React.SyntheticEvent) => {
setMessage(`Editing cell with value: ${param.value} at row: ${param.rowIndex}, column: ${
param.field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default {
defaultValue: 2000,
control: {
type: 'select',
options: [100, 500, 1000, 2000, 5000, 8000, 10000, 50000, 100000, 500000],
options: [10, 50, 100, 500, 1000, 2000, 5000, 8000, 10000, 50000, 100000, 500000],
},
},
multipleGrid: {
Expand Down