Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
1fb9dc2
Extract reusable stuff to Pro package
MBilalShafi Sep 2, 2025
e2c0928
Initial stub for treeDataReorderValidator
MBilalShafi Sep 2, 2025
01d7ef9
Add a demo
MBilalShafi Sep 2, 2025
1e4a820
Support same parent reordering (simple use case)
MBilalShafi Sep 2, 2025
a92b8a0
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 7, 2025
cd6a63e
Update the demo to 2 levels
MBilalShafi Sep 8, 2025
319d5e8
Remove irrelevant validation cases
MBilalShafi Sep 8, 2025
edf71dc
Updates
MBilalShafi Sep 8, 2025
eedddb0
Add setTreeDataPath() prop
MBilalShafi Sep 8, 2025
92be312
Implement cross parent leaf operation
MBilalShafi Sep 8, 2025
119b90b
Add CrossParentGroupOperation
MBilalShafi Sep 8, 2025
b4a1b04
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 16, 2025
a32cff2
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 19, 2025
2a69d6b
Add 'over' position and move the drop indicator to overlay
MBilalShafi Sep 19, 2025
4136ed4
Revert to the pseudo element approach
MBilalShafi Sep 19, 2025
8edd70f
Allow executor to access dropPosition
MBilalShafi Sep 19, 2025
099ebc7
✨ Add drop on leaf use-case
MBilalShafi Sep 19, 2025
b9df30b
💬 Some formatting
MBilalShafi Sep 19, 2025
8669fe4
🎋 Allow to expand tree data rows at any nested level by hovering + im…
MBilalShafi Sep 19, 2025
71174e9
Add isRowOrderable
MBilalShafi Sep 19, 2025
cc547e7
➕ Introduce isValidRowReorder prop
MBilalShafi Sep 19, 2025
4ea0c3c
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 19, 2025
b36a709
Fix circular dependency
MBilalShafi Sep 19, 2025
c6d8874
Regenerate docs
MBilalShafi Sep 19, 2025
e50a2c2
Add missing props
MBilalShafi Sep 19, 2025
2b3b53c
Improve docs
MBilalShafi Sep 19, 2025
4bb3b57
Fix flickering during dragOver
MBilalShafi Sep 20, 2025
becedc5
Remove possibility to drop a group on one of it's own descendants
MBilalShafi Sep 20, 2025
7546e11
Update isValidRowReorder to respect internal validation boundaries
MBilalShafi Sep 20, 2025
7d2aa25
Update demo
MBilalShafi Sep 20, 2025
8ce8c91
Wait for async operations to complete before publishing event
MBilalShafi Sep 20, 2025
51479a2
Lint
MBilalShafi Sep 21, 2025
48e21db
Use proper methods for all the use-cases, irrespective of package
MBilalShafi Sep 21, 2025
cb2ec34
Widen the grid configuration types a bit
MBilalShafi Sep 22, 2025
667fae4
Cleanup
MBilalShafi Sep 22, 2025
4d50c07
Export public types
MBilalShafi Sep 22, 2025
2237538
Add a couple docs' sections
MBilalShafi Sep 22, 2025
33d2b32
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 22, 2025
6fc3662
docs:api
MBilalShafi Sep 22, 2025
cba173a
Generate proper signature in API documentation
MBilalShafi Sep 22, 2025
e2a6040
Minor docs update
MBilalShafi Sep 22, 2025
1c871e8
Add test coverage
MBilalShafi Sep 23, 2025
d814eae
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 23, 2025
180deac
Add a selector
MBilalShafi Sep 23, 2025
ddb778f
Add a demo to sync with external rows object
MBilalShafi Sep 23, 2025
ac37fe4
docs:api
MBilalShafi Sep 23, 2025
1a5b2e3
Fix a few breaking tests
MBilalShafi Sep 23, 2025
e8db417
Fix more tests
MBilalShafi Sep 23, 2025
f44ddb1
Fix: Lint
MBilalShafi Sep 23, 2025
633d121
Improve tests
MBilalShafi Sep 23, 2025
e8831a5
Merge remote-tracking branch 'upstream/master' into tree-data-row-gro…
MBilalShafi Sep 25, 2025
957db89
Merge remote-tracking branch 'upstream/master' into tree-data-row-gro…
MBilalShafi Sep 29, 2025
0c379a4
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 29, 2025
3aa1ce7
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Sep 30, 2025
922b1c9
Remove the hack thanks to #19697
MBilalShafi Sep 30, 2025
9a9fd0e
Improve docs
MBilalShafi Oct 1, 2025
dc6022b
Apply suggestion from @arminmeh
MBilalShafi Oct 1, 2025
747ab9c
Apply suggestion from @siriwatknp
MBilalShafi Oct 1, 2025
70eddf5
Apply suggestion from @arminmeh
MBilalShafi Oct 1, 2025
5e3a4af
remove unused imports
arminmeh Oct 3, 2025
7581156
Finish todo
arminmeh Oct 3, 2025
eaa8ff9
Merge branch 'master' into tree-data-row-grouping
MBilalShafi Oct 15, 2025
3edcca9
Docs improvements
MBilalShafi Oct 15, 2025
a65a901
Make the demo use 'Tree data'
MBilalShafi Oct 15, 2025
f27b224
Update heading
MBilalShafi Oct 15, 2025
33086af
A few updates on tests
MBilalShafi Oct 17, 2025
7122b37
Test updates
MBilalShafi Oct 17, 2025
118d9bb
Simplify await calls
MBilalShafi Oct 17, 2025
fd6f65d
Cleanup unused classes
MBilalShafi Oct 17, 2025
7607b63
Cleanup outdated test
MBilalShafi Oct 17, 2025
e8ce355
Clean up a couple conditions
MBilalShafi Oct 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/data/data-grid/row-ordering/RowReorderingDisabled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';
import { DataGridPro } from '@mui/x-data-grid-pro';
import { useDemoData } from '@mui/x-data-grid-generator';

const isRowReorderable = (params) => {
return params.row.quantity < 50000;
};

export default function RowReorderingDisabled() {
const { data, loading } = useDemoData({
dataSet: 'Commodity',
rowLength: 20,
maxColumns: 20,
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
{...data}
loading={loading}
rowReordering
isRowReorderable={isRowReorderable}
/>
</div>
);
}
26 changes: 26 additions & 0 deletions docs/data/data-grid/row-ordering/RowReorderingDisabled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';
import { DataGridPro, type IsRowReorderableParams } from '@mui/x-data-grid-pro';
import { useDemoData } from '@mui/x-data-grid-generator';

const isRowReorderable = (params: IsRowReorderableParams) => {
return params.row.quantity < 50000;
};

export default function RowReorderingDisabled() {
const { data, loading } = useDemoData({
dataSet: 'Commodity',
rowLength: 20,
maxColumns: 20,
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
{...data}
loading={loading}
rowReordering
isRowReorderable={isRowReorderable}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<DataGridPro
{...data}
loading={loading}
rowReordering
isRowReorderable={isRowReorderable}
/>
42 changes: 42 additions & 0 deletions docs/data/data-grid/row-ordering/RowReorderingValidation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from 'react';
import { DataGridPro } from '@mui/x-data-grid-pro';
import { useDemoData } from '@mui/x-data-grid-generator';

const isValidRowReorder = (context) => {
if (context.sourceNode.type === 'group') {
return true;
}
if (context.targetNode.type === 'leaf') {
return context.sourceNode.parent !== context.targetNode.parent;
}
return false;
};

const getTreeDataPath = (row) => {
return row.path;
};

const setTreeDataPath = (path, row) => {
return { ...row, path };
};

export default function RowReorderingValidation() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
rowLength: 100,
treeData: { maxDepth: 2, groupingField: 'name', averageChildren: 4 },
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
{...data}
setTreeDataPath={setTreeDataPath}
getTreeDataPath={getTreeDataPath}
loading={loading}
rowReordering
isValidRowReorder={isValidRowReorder}
/>
</div>
);
}
46 changes: 46 additions & 0 deletions docs/data/data-grid/row-ordering/RowReorderingValidation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as React from 'react';
import {
DataGridPro,
GridValidRowModel,
ReorderValidationContext,
} from '@mui/x-data-grid-pro';
import { useDemoData } from '@mui/x-data-grid-generator';

const isValidRowReorder = (context: ReorderValidationContext) => {
if (context.sourceNode.type === 'group') {
return true;
}
if (context.targetNode.type === 'leaf') {
return context.sourceNode.parent !== context.targetNode.parent;
}
return false;
};

const getTreeDataPath = (row: GridValidRowModel) => {
return row.path;
};

const setTreeDataPath = (path: string[], row: GridValidRowModel) => {
return { ...row, path };
};

export default function RowReorderingValidation() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
rowLength: 100,
treeData: { maxDepth: 2, groupingField: 'name', averageChildren: 4 },
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
{...data}
setTreeDataPath={setTreeDataPath}
getTreeDataPath={getTreeDataPath}
loading={loading}
rowReordering
isValidRowReorder={isValidRowReorder}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<DataGridPro
{...data}
setTreeDataPath={setTreeDataPath}
getTreeDataPath={getTreeDataPath}
loading={loading}
rowReordering
isValidRowReorder={isValidRowReorder}
/>
39 changes: 35 additions & 4 deletions docs/data/data-grid/row-ordering/row-ordering.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,45 @@ This approach can also be used to change the location of the toggle column.
For now, row reordering is disabled if sorting is applied to the Data Grid.
:::

## Row reordering with tree data 🚧
## Disable reordering of specific rows

To disable reordering of specific rows, you can pass a callback to the `isRowReorderable()` prop.
This callback is called with `row` and `rowNode` objects to allow disabling rows based on multiple criteria.

```tsx
<DataGridPro isRowReorderable={isRowReorderable} />
```

The demo below shows how to disable reordering of specific rows based on the row model.

{{"demo": "RowReorderingDisabled.js", "bg": "inline"}}

## Disable specific reorder operations

Sometimes, the information provided by the source row isn't enough to determine if a reorder operation is valid.
In these cases, you can pass a callback to the `isValidRowReorder()` prop.

This callback is fired _during_ the drag operation so it provides information about the dragged row and potential row where it is being dropped.
It is called with a `ReorderValidationContext` object to allow disabling specific reorder operations based on the context.

The demo below prohibits reordering leaf rows under the same parent and only allows cross-parent operations.

{{"demo": "RowReorderingValidation.js", "bg": "inline"}}

:::warning
This feature isn't available yet, but it is planned—you can 👍 upvote [this GitHub issue](https://github.com/mui/mui-x/issues/7774) to help us prioritize it.
Please don't hesitate to leave a comment there to describe your needs, especially if you have a use case we should address or you're facing specific pain points with your current solution.
The row reorder feature has an internal validation ruleset that makes sure that only the supported use-cases are allowed.
`isValidRowReorder()` should only be used to omit some of the supported use-cases, not add new ones.
:::

With this feature, users would be able to reorder rows in use cases that also involve tree data and/or row grouping.
:::info
The above demo uses row grouping to demonstrate the concept. You can check more about this in the [Tree data—Drag-and-drop tree data reordering](/x/react-data-grid/tree-data/#drag-and-drop-tree-data-reordering) documentation section.
:::

## Row reordering with tree data

Users can drag and drop rows to move between parents, or convert leaf nodes into parent groups.

For more details, see [Tree data—Drag-and-drop tree data reordering](/x/react-data-grid/tree-data/#drag-and-drop-tree-data-reordering).

## Row reordering with row grouping [<span class="plan-premium"></span>](/x/introduction/licensing/#premium-plan 'Premium plan')

Expand Down
35 changes: 35 additions & 0 deletions docs/data/data-grid/tree-data/TreeDataReordering.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from 'react';
import { DataGridPro } from '@mui/x-data-grid-pro';
import { useDemoData } from '@mui/x-data-grid-generator';

const getTreeDataPath = (row) => {
return row.path;
};

const setTreeDataPath = (path, row) => {
return {
...row,
path,
};
};

export default function TreeDataReordering() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
rowLength: 100,
treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 2 },
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
{...data}
loading={loading}
rowReordering
disableRowSelectionOnClick
getTreeDataPath={getTreeDataPath}
setTreeDataPath={setTreeDataPath}
/>
</div>
);
}
35 changes: 35 additions & 0 deletions docs/data/data-grid/tree-data/TreeDataReordering.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from 'react';
import { DataGridPro, type DataGridProProps } from '@mui/x-data-grid-pro';
import { useDemoData } from '@mui/x-data-grid-generator';

const getTreeDataPath: DataGridProProps['getTreeDataPath'] = (row) => {
return row.path;
};

const setTreeDataPath: DataGridProProps['setTreeDataPath'] = (path, row) => {
return {
...row,
path,
};
};

export default function TreeDataReordering() {
const { data, loading } = useDemoData({
dataSet: 'Employee',
rowLength: 100,
treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 2 },
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
{...data}
loading={loading}
rowReordering
disableRowSelectionOnClick
getTreeDataPath={getTreeDataPath}
setTreeDataPath={setTreeDataPath}
/>
</div>
);
}
8 changes: 8 additions & 0 deletions docs/data/data-grid/tree-data/TreeDataReordering.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<DataGridPro
{...data}
loading={loading}
rowReordering
disableRowSelectionOnClick
getTreeDataPath={getTreeDataPath}
setTreeDataPath={setTreeDataPath}
/>
Loading
Loading