mui-x icon indicating copy to clipboard operation
mui-x copied to clipboard

[DataGridPro] Data source nested pagination recipe

Open MBilalShafi opened this issue 1 year ago • 4 comments

Allows the pagination of any nested level of the tree data. A possible solution for #14527 in the userland

https://deploy-preview-14777--material-ui-x.netlify.app/x/react-data-grid/server-side-data/recipes/


In progress

  • [x] Refine behavior with filtering, sorting, etc.
  • [ ] ~~Check if the cache could be integrated with it~~ it could not
  • [x] Optional: Retain the paginationModel state for each nested level.
  • [ ] ~~Optional: Retain unique filterModel and sortModel states for each nested level.~~ makes more sense without it
  • [x] List the limitations of the recipe

Follow-up

  • [ ] Implement with row grouping

MBilalShafi avatar Sep 30 '24 12:09 MBilalShafi

Deploy preview: https://deploy-preview-14777--material-ui-x.netlify.app/

Updated pages:

Bundle size report

Total Size Change: 🔺+114B(0.00%) - Total Gzip Change: 🔺+22B(0.00%) Files: 122 total (0 added, 0 removed, 6 changed)

Show details for 100 more bundles (22 more not shown)

@mui/x-data-gridparsed: 🔺+19B(0.00%) gzip: 🔺+3B(0.00%) @mui/x-data-grid-premiumparsed: 🔺+19B(0.00%) gzip: 🔺+1B(0.00%) @mui/x-data-grid-premium/DataGridPremiumparsed: 🔺+19B(0.00%) gzip: 🔺+2B(0.00%) @mui/x-data-grid-proparsed: 🔺+19B(0.00%) gzip: 🔺+8B(+0.01%) @mui/x-data-grid-pro/DataGridProparsed: 🔺+19B(0.00%) gzip: 🔺+3B(0.00%) @mui/x-data-grid/DataGridparsed: 🔺+19B(+0.01%) gzip: 🔺+5B(0.00%) @mui/x-chartsparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-proparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/BarChartProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/ChartContainerProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/ChartDataProviderProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/ChartsToolbarProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/ChartZoomSliderparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/FunnelChartparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/Heatmapparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/LineChartProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/PieChartProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/RadarChartProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts-pro/ScatterChartProparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/BarChartparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartContainerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartDataProviderparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsAxisparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsAxisHighlightparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsClipPathparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsGridparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsLabelparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsLegendparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsLocalizationProviderparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsOverlayparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsReferenceLineparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsSurfaceparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsTextparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsTooltipparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsXAxisparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ChartsYAxisparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/Gaugeparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/LineChartparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/PieChartparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/RadarChartparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/ScatterChartparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/SparkLineChartparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-charts/Toolbarparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickersparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-proparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/AdapterDateFnsparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/AdapterDateFnsJalaliparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/AdapterDayjsparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/AdapterLuxonparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/AdapterMomentparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/AdapterMomentHijriparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/AdapterMomentJalaaliparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DateRangeCalendarparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DateRangePickerDayparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DateRangePickerDay2parsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DateTimeRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DesktopDateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DesktopDateTimeRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/DesktopTimeRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/LocalizationProviderparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/MobileDateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/MobileDateTimeRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/MobileTimeRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/MultiInputDateRangeFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/MultiInputDateTimeRangeFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/MultiInputTimeRangeFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/PickersRangeCalendarHeaderparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/SingleInputDateRangeFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/SingleInputDateTimeRangeFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/SingleInputTimeRangeFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/StaticDateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers-pro/TimeRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterDateFnsparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterDateFnsBaseparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterDateFnsJalaliparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterDayjsparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterLuxonparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterMomentparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterMomentHijriparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/AdapterMomentJalaaliparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DateCalendarparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DateFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DatePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DateTimeFieldparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DateTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DayCalendarSkeletonparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DesktopDatePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DesktopDateTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DesktopTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/DigitalClockparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/LocalizationProviderparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/MobileDatePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/MobileDateTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/MobileTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/MonthCalendarparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/MultiSectionDigitalClockparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/PickerDay2parsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/PickersActionBarparsed: 0B(0.00%) gzip: 0B(0.00%) @mui/x-date-pickers/PickersCalendarHeaderparsed: 0B(0.00%) gzip: 0B(0.00%)

Details of bundle changes

Generated by :no_entry_sign: dangerJS against a4bf79980da41fcf94ece3b5bab78a675cf50945

mui-bot avatar Sep 30 '24 12:09 mui-bot

Looking good, noticed one issue where top level items are temporarily nested under the newly expanded row whilst the children are loading:

image image

kenanyusuf avatar Sep 30 '24 15:09 kenanyusuf

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Oct 25 '24 07:10 github-actions[bot]

Thanks for adding a type label to the PR! 👍

github-actions[bot] avatar May 07 '25 16:05 github-actions[bot]

I have noticed that the data source is called twice if you change the expansion after the page is being changed

https://github.com/user-attachments/assets/27f7f41a-5e05-44ff-b540-ce86682328b8

arminmeh avatar Jun 17 '25 06:06 arminmeh

I have noticed that the data source is called twice if you change the expansion after the page is being changed

This happens because we maintain separate pagination states for each nested level and reset them when you switch levels. The first dataSource call occurs due to the dataSource instance being updated, and the second happens when we set the pagination state (paginationModel)

Other than making an additional API call, this shouldn’t cause any issues, because the second call simply overrides the first.

We could avoid this by not keeping separate pagination state for each level, but that would result in a less convenient UX. So in this context, I think trading off a single extra call for a better UX is reasonable.

What do you think?

MBilalShafi avatar Jun 17 '25 16:06 MBilalShafi

So in this context, I think trading off a single extra call for a better UX is reasonable.

Agree, since the demo should not take care of this. It should be handled internally

Maybe having debounced fetch row here would help https://github.com/mui/mui-x/blob/v8.5.2/packages/x-data-grid/src/hooks/features/dataSource/useGridDataSourceBase.ts#L272

The proper way would be implementing https://github.com/mui/mui-x/issues/18253

In any case, I am fine with merging this recipe like it is now. Not sure if you want @mapache-salvaje to check the small docs updates that were made.

arminmeh avatar Jun 17 '25 16:06 arminmeh

This pull request has conflicts, please resolve those before we can evaluate the pull request.

github-actions[bot] avatar Jun 20 '25 07:06 github-actions[bot]

@mapache-salvaje I merged this one since the changes were not huge, feel free to leave your feedback on documentation aspect of it if you want, and I'll accommodate it in the follow-up PR.

MBilalShafi avatar Jun 24 '25 12:06 MBilalShafi