Skip to content

Commit 1ecfce5

Browse files
authored
[DataGridPro] Improve trigger for nested row reordering (#21642)
1 parent d62ab66 commit 1ecfce5

4 files changed

Lines changed: 61 additions & 11 deletions

File tree

packages/x-data-grid-premium/src/hooks/features/rows/useGridRowsOverridableMethods.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export const useGridRowsOverridableMethods = (
128128
[apiRef, processRowUpdate, onProcessRowUpdateError],
129129
);
130130

131-
if (flatTree) {
131+
if (flatTree && !props.treeData) {
132132
return {
133133
setRowIndex: setRowIndexPlain,
134134
setRowPosition: setRowPositionPlain,

packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { useMaterialCSSVariables } from '@mui/x-data-grid/material';
1414
import { forwardRef } from '@mui/x-internals/forwardRef';
1515
import { useGridRowsOverridableMethods } from '../hooks/features/rows/useGridRowsOverridableMethods';
1616
import { useDataGridProComponent } from './useDataGridProComponent';
17-
import type { DataGridProProps } from '../models/dataGridProProps';
17+
import type { DataGridProProcessedProps, DataGridProProps } from '../models/dataGridProProps';
1818
import { useDataGridProProps } from './useDataGridProProps';
1919
import { propValidatorsDataGridPro } from '../internals/propValidation';
2020
import { useGridAriaAttributesPro } from '../hooks/utils/useGridAriaAttributes';
@@ -23,7 +23,7 @@ import type { GridApiPro, GridPrivateApiPro } from '../models/gridApiPro';
2323

2424
export type { GridProSlotsComponent as GridSlots } from '../models';
2525

26-
const configuration: GridConfiguration<GridPrivateApiPro> = {
26+
const configuration: GridConfiguration<GridPrivateApiPro, DataGridProProcessedProps> = {
2727
hooks: {
2828
useCSSVariables: useMaterialCSSVariables,
2929
useGridAriaAttributes: useGridAriaAttributesPro,

packages/x-data-grid-pro/src/hooks/features/rows/useGridRowsOverridableMethods.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import {
33
gridRowTreeSelector,
44
gridExpandedSortedRowIdsSelector,
55
gridRowNodeSelector,
6-
useGridSelector,
7-
gridRowMaximumTreeDepthSelector,
86
gridExpandedSortedRowIndexLookupSelector,
97
type GridRowProApi,
108
} from '@mui/x-data-grid';
@@ -19,15 +17,13 @@ export const useGridRowsOverridableMethods = (
1917
apiRef: RefObject<GridPrivateApiPro>,
2018
props: Pick<
2119
DataGridProProcessedProps,
22-
'processRowUpdate' | 'onProcessRowUpdateError' | 'setTreeDataPath'
20+
'processRowUpdate' | 'onProcessRowUpdateError' | 'setTreeDataPath' | 'treeData'
2321
>,
2422
) => {
25-
const { processRowUpdate, onProcessRowUpdateError, setTreeDataPath } = props;
23+
const { processRowUpdate, onProcessRowUpdateError, setTreeDataPath, treeData } = props;
2624
const { setRowIndex: setRowIndexFlat, setRowPosition: setRowPositionFlat } =
2725
useGridRowsOverridableMethodsCommunity(apiRef);
2826

29-
const flatTree = useGridSelector(apiRef, gridRowMaximumTreeDepthSelector) === 1;
30-
3127
const setRowPosition = React.useCallback<GridRowProApi['setRowPosition']>(
3228
async (sourceRowId, targetRowId, position) => {
3329
const sortedFilteredRowIds = gridExpandedSortedRowIdsSelector(apiRef);
@@ -101,7 +97,7 @@ export const useGridRowsOverridableMethods = (
10197
}, []);
10298

10399
return {
104-
setRowIndex: flatTree ? setRowIndexFlat : setRowIndex,
105-
setRowPosition: flatTree ? setRowPositionFlat : setRowPosition,
100+
setRowIndex: treeData ? setRowIndex : setRowIndexFlat,
101+
setRowPosition: treeData ? setRowPosition : setRowPositionFlat,
106102
};
107103
};

packages/x-data-grid-pro/src/tests/rowReorderTreeData.DataGridPro.test.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,60 @@ describe.skipIf(isJSDOM)('<DataGridPro /> - Tree data row reordering', () => {
825825
// Verify all paths maintain correct hierarchy
826826
expect(updatedRows.length).to.equal(2); // Project + File.doc
827827
});
828+
829+
it('should allow dropping inside when initial data has no children (all rows at root level)', async () => {
830+
// Regression test for https://github.com/mui/mui-x/issues/21347
831+
// When treeData is enabled but all rows are flat (no parent-child relationships),
832+
// the "inside" drop position should still work.
833+
const handleRowOrderChange = spy();
834+
const processedRows: GridRowModel[] = [];
835+
836+
const handleProcessRowUpdate = (newRow: GridRowModel) => {
837+
processedRows.push(newRow);
838+
return newRow;
839+
};
840+
841+
render(
842+
<Test
843+
onRowOrderChange={handleRowOrderChange}
844+
processRowUpdate={handleProcessRowUpdate}
845+
rows={[
846+
{ id: 1, path: ['Folder'], name: 'Folder' },
847+
{ id: 2, path: ['FileA'], name: 'FileA' },
848+
{ id: 3, path: ['FileB'], name: 'FileB' },
849+
]}
850+
/>,
851+
);
852+
853+
const allValues = getColumnValues(0);
854+
const fileAIndex = findRowIndex(allValues, 'FileA', 2);
855+
const folderIndex = findRowIndex(allValues, 'Folder', 1);
856+
857+
expect(fileAIndex).to.be.greaterThan(
858+
-1,
859+
`FileA should be found in: ${allValues.join(', ')}`,
860+
);
861+
expect(folderIndex).to.be.greaterThan(
862+
-1,
863+
`Folder should be found in: ${allValues.join(', ')}`,
864+
);
865+
866+
const sourceCell = getCell(fileAIndex, 0).firstChild!;
867+
const targetCell = getCell(folderIndex, 0);
868+
869+
performDragOperation(sourceCell, targetCell, 'inside');
870+
871+
await waitFor(() => {
872+
expect(handleRowOrderChange.callCount).to.equal(1);
873+
});
874+
875+
// Verify FileA is now a child of Folder
876+
const rowTree = gridRowTreeSelector(apiRef!);
877+
const fileANode = rowTree[2];
878+
const folderNode = rowTree[1];
879+
expect(folderNode.type).to.equal('group');
880+
expect(fileANode.parent).to.equal(folderNode.id);
881+
});
828882
});
829883
});
830884

0 commit comments

Comments
 (0)