Skip to content

Commit

Permalink
[DataGridPro] Make Row reordering work with pagination (@k-rajat19) (#…
Browse files Browse the repository at this point in the history
…15782)

Co-authored-by: Rajat <[email protected]>
Co-authored-by: Bilal Shafi <[email protected]>
  • Loading branch information
3 people authored Dec 10, 2024
1 parent ac803d7 commit ea8ce4e
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import {
useGridApiOptionHandler,
GridRowId,
} from '@mui/x-data-grid';
import { gridEditRowsStateSelector } from '@mui/x-data-grid/internals';
import {
gridEditRowsStateSelector,
gridSortedRowIndexLookupSelector,
} from '@mui/x-data-grid/internals';
import { GridRowOrderChangeParams } from '../../../models/gridRowOrderChangeParams';
import { GridPrivateApiPro } from '../../../models/gridApiPro';
import { DataGridProProcessedProps } from '../../../models/dataGridProProps';
Expand Down Expand Up @@ -63,6 +66,7 @@ export const useGridRowReorder = (
const ownerState = { classes: props.classes };
const classes = useUtilityClasses(ownerState);
const [dragRowId, setDragRowId] = React.useState<GridRowId>('');
const sortedRowIndexLookup = useGridSelector(apiRef, gridSortedRowIndexLookupSelector);

React.useEffect(() => {
return () => {
Expand Down Expand Up @@ -91,17 +95,16 @@ export const useGridRowReorder = (

dragRowNode.current = event.currentTarget;
dragRowNode.current.classList.add(classes.rowDragging);

setDragRowId(params.id);

removeDnDStylesTimeout.current = setTimeout(() => {
dragRowNode.current!.classList.remove(classes.rowDragging);
});

originRowIndex.current = apiRef.current.getRowIndexRelativeToVisibleRows(params.id);
originRowIndex.current = sortedRowIndexLookup[params.id];
apiRef.current.setCellFocus(params.id, GRID_REORDER_COL_DEF.field);
},
[isRowReorderDisabled, classes.rowDragging, logger, apiRef],
[apiRef, isRowReorderDisabled, logger, classes.rowDragging, sortedRowIndexLookup],
);

const handleDragOver = React.useCallback<GridEventListener<'cellDragOver' | 'rowDragOver'>>(
Expand All @@ -127,7 +130,7 @@ export const useGridRowReorder = (
: event.clientY;

if (params.id !== dragRowId) {
const targetRowIndex = apiRef.current.getRowIndexRelativeToVisibleRows(params.id);
const targetRowIndex = sortedRowIndexLookup[params.id];

const dragDirection = mouseMovementDiff > 0 ? Direction.DOWN : Direction.UP;
const currentReorderState: ReorderStateProps = {
Expand All @@ -149,7 +152,7 @@ export const useGridRowReorder = (

previousMousePosition = { x: event.clientX, y: event.clientY };
},
[apiRef, logger, dragRowId],
[dragRowId, apiRef, logger, sortedRowIndexLookup],
);

const handleDragEnd = React.useCallback<GridEventListener<'rowDragEnd'>>(
Expand Down Expand Up @@ -179,7 +182,7 @@ export const useGridRowReorder = (
// Emit the rowOrderChange event only once when the reordering stops.
const rowOrderChangeParams: GridRowOrderChangeParams = {
row: apiRef.current.getRow(dragRowId)!,
targetIndex: apiRef.current.getRowIndexRelativeToVisibleRows(params.id),
targetIndex: sortedRowIndexLookup[params.id],
oldIndex: originRowIndex.current!,
};

Expand All @@ -188,7 +191,7 @@ export const useGridRowReorder = (

setDragRowId('');
},
[isRowReorderDisabled, logger, apiRef, dragRowId],
[apiRef, dragRowId, isRowReorderDisabled, logger, sortedRowIndexLookup],
);

useGridApiEventHandler(apiRef, 'rowDragStart', handleDragStart);
Expand Down
50 changes: 48 additions & 2 deletions packages/x-data-grid-pro/src/tests/rowReorder.DataGridPro.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { createRenderer, fireEvent, createEvent } from '@mui/internal-test-utils';
import { getCell, getRowsFieldContent } from 'test/utils/helperFn';
import { createRenderer, fireEvent, screen, createEvent } from '@mui/internal-test-utils';
import { getCell, getColumnValues, getRowsFieldContent } from 'test/utils/helperFn';
import { useGridApiRef, DataGridPro, gridClasses, GridApi } from '@mui/x-data-grid-pro';
import { useBasicDemoData } from '@mui/x-data-grid-generator';

Expand Down Expand Up @@ -200,4 +200,50 @@ describe('<DataGridPro /> - Row reorder', () => {
expect(handleDragOver.callCount).to.equal(0);
expect(handleDragEnd.callCount).to.equal(0);
});

it('should reorder rows correctly on any page when pagination is enabled', () => {
let apiRef: React.MutableRefObject<GridApi>;
const rows = [
{ id: 0, brand: 'Nike' },
{ id: 1, brand: 'Adidas' },
{ id: 2, brand: 'Puma' },
{ id: 3, brand: 'Skechers' },
];
const columns = [{ field: 'brand' }];

function Test() {
apiRef = useGridApiRef();

return (
<div style={{ width: 300, height: 300 }}>
<DataGridPro
apiRef={apiRef}
rows={rows}
columns={columns}
rowReordering
pagination
initialState={{
pagination: {
paginationModel: { pageSize: 2 },
},
}}
pageSizeOptions={[2]}
/>
</div>
);
}

render(<Test />);
fireEvent.click(screen.getByRole('button', { name: /next page/i }));
expect(getColumnValues(0)).to.deep.equal(['2', '3']);
expect(getRowsFieldContent('brand')).to.deep.equal(['Puma', 'Skechers']);
const rowReorderCell = getCell(2, 0).firstChild!;
const targetCell = getCell(3, 0);

fireEvent.dragStart(rowReorderCell);
fireEvent.dragEnter(targetCell);
const dragOverEvent = createDragOverEvent(targetCell);
fireEvent(targetCell, dragOverEvent);
expect(getRowsFieldContent('brand')).to.deep.equal(['Skechers', 'Puma']);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { GridSortDirection, GridSortModel } from '../../../models/gridSortModel'
import { gridRowTreeSelector, gridRowsLookupSelector } from '../rows/gridRowsSelector';
import { GRID_ID_AUTOGENERATED, isAutogeneratedRowNode } from '../rows/gridRowsUtils';
import type { GridStateCommunity } from '../../../models/gridStateCommunity';
import type { GridValidRowModel, GridRowEntry } from '../../../models/gridRows';
import type { GridValidRowModel, GridRowEntry, GridRowId } from '../../../models/gridRows';

/**
* @category Sorting
Expand Down Expand Up @@ -73,3 +73,17 @@ export const gridSortColumnLookupSelector = createSelectorMemoized(
return result;
},
);

/**
* @category Sorting
* @ignore - do not document.
*/
export const gridSortedRowIndexLookupSelector = createSelectorMemoized(
gridSortedRowIdsSelector,
(sortedIds) => {
return sortedIds.reduce<Record<GridRowId, number>>((acc, id, index) => {
acc[id] = index;
return acc;
}, Object.create(null));
},
);
8 changes: 7 additions & 1 deletion packages/x-data-grid/src/hooks/features/sorting/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
export * from './gridSortingSelector';
export {
gridSortedRowIdsSelector,
gridSortedRowEntriesSelector,
gridSortModelSelector,
gridSortColumnLookupSelector,
} from './gridSortingSelector';
export type { GridSortColumnLookup } from './gridSortingSelector';
export type { GridSortingState, GridSortingInitialState } from './gridSortingState';
export {
gridDateComparator,
Expand Down
1 change: 1 addition & 0 deletions packages/x-data-grid/src/internals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export {
export { useGridRowSelectionPreProcessors } from '../hooks/features/rowSelection/useGridRowSelectionPreProcessors';
export { useGridSorting, sortingStateInitializer } from '../hooks/features/sorting/useGridSorting';
export type { GridSortingModelApplier } from '../hooks/features/sorting/gridSortingState';
export { gridSortedRowIndexLookupSelector } from '../hooks/features/sorting/gridSortingSelector';
export { useGridScroll } from '../hooks/features/scroll/useGridScroll';
export { useGridEvents } from '../hooks/features/events/useGridEvents';
export {
Expand Down

0 comments on commit ea8ce4e

Please sign in to comment.