mui / mui-x

MUI X: Build complex and data-rich applications using a growing list of advanced React components, like the Data Grid, Date and Time Pickers, Charts, and more!
https://mui.com/x/
3.9k stars 1.19k forks source link

[Data grid] Controlled column ordering #5704

Open DeanFromLondon opened 1 year ago

DeanFromLondon commented 1 year ago

Order ID 💳

48444

Duplicates

Related issues: https://github.com/mui/mui-x/issues/5418 https://github.com/mui/mui-x/issues/5461 https://github.com/mui/mui-x/issues/4950

Latest version

The problem in depth 🔍

I am trying to retain the new reordered columns between refreshes by saving it to LocalStorage. This should allow the user to save it's customised view of the DataGrid table.

I went through the documentation and searched through issues here and in stackoverflow. It appears that the only way to set the order of the columns is by changing their default order when setting the columns prop.

As an attempt to walk-around this issue, I tried saving the newly changed index of columns after every column change (using onColumnOrderChange) but didn't succeed (caused re-rendering issues and faulty column moves functionality when attempted to push GridColDef objects into Columns:GridColDef[] array.).

Your environment 🌎

`npx @mui/envinfo` ``` System: OS: macOS 12.4 Binaries: Node: 17.9.0 - ~/.nvm/versions/node/v17.9.0/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v17.9.0/bin/yarn npm: 8.5.5 - ~/.nvm/versions/node/v17.9.0/bin/npm Browsers: Chrome: 104.0.5112.79 - Tested Edge: Not Found Firefox: 103.0.1 - Tested Safari: 15.5 - Tested ```
cherniavskii commented 1 year ago

Hey @DeanFromLondon Did you try state import / export? Sound like it should work for your use case

DeanFromLondon commented 1 year ago

Thank you for your reply! I am managing several states manually (such as pagination, server side filtering, server side sorting) and exporting/importing their values. I will try to combine them with exporting the state and importing only the column order. Is there an option to control column order with props, same way as I control the attributes mentioned above?

cherniavskii commented 1 year ago

Is there an option to control column order with props, same way as I control the attributes mentioned above?

Not really, but controlled column ordering might be a good addition to the API. Similar to controlled column pinning, it would add two props - one with ordered column fields, and a callback that would be called when user changes columns order.

DeanFromLondon commented 1 year ago

Hello again @cherniavskii, Sorry for the delayed response. This matter had been in the backlog for some time but I am finally able to address it.

The state API's import/export methods solved my issue, but both still print out a warning:

  1. Warning: Failed prop type: The prop apiRef.current is marked as required in ForwardRef(DataGridPro), but its value is null.
  2. Warning: Failed prop type: Invalid prop initialState of type string supplied to ForwardRef(DataGridPro), expected object.

Is there an option to control column order with props, same way as I control the attributes mentioned above?

Not really, but controlled column ordering might be a good addition to the API. Similar to controlled column pinning, it would add two props - one with ordered column fields, and a callback that would be called when user changes columns order.

This sounds like a great solution for the problem and it is just what I had in mind opening this issue. Please let me know if I should upvote (👍) this topic anywhere else.

cherniavskii commented 1 year ago

Hey @DeanFromLondon

The issue I am experiencing with instance B is the columns are bouncing around

This sounds like a bug. Can you share a minimal reproduction example?

Disabling onColumnOrderChange stops them from bouncing around and allows me to reorder the columns, but then of course I cannot save the state for later use.

If you're using onColumnOrderChange only to persist column ordering state, you should not need it since exportState should also export column order state.

DeanFromLondon commented 1 year ago

@cherniavskii Thank you for your quick reply!

I have managed to solve the issue described yesterday by changing the columns from a regular const to a React state. I have updated the comment thinking you would be able to address the latest issue but you were replying just as I was editing it :)

The tables still issue a warning as described in my last comment.

If you're using onColumnOrderChange only to persist column ordering state, you should not need it since exportState should also export column order state.

I am using onColumnOrderChange to invoke the exportState method. Would you suggest using any other event to detect changes in the columns order?

cherniavskii commented 1 year ago

@DeanFromLondon

I have managed to solve the issue described yesterday by changing the columns from a regular const to a React state.

Yeah, columns have to be memoized, otherwise column order will reset on the next render. You can also use React.useMemo instead of state (unless you need state to update columns)

I am using onColumnOrderChange to invoke the exportState method.

Makes sense then :+1:

TamirCode commented 1 year ago

Is there an option to control column order with props, same way as I control the attributes mentioned above?

Not really, but controlled column ordering might be a good addition to the API. Similar to controlled column pinning, it would add two props - one with ordered column fields, and a callback that would be called when user changes columns order.

i need a way to set column order (so it would be controlled) and initialState is broken as well https://github.com/mui/mui-x/issues/6206

we have a onColumnOrderChange prop, now we just need a columnOrder prop, just like we have onColumnVisibilityModelChange and columnVisibilityModel

will also be included in apiRef.current.setColumnOrder

so definitely implement this essential feature, every time my dynamic data changes it resets their column order

hafley66 commented 1 year ago

It would be really nice to have a consistent api, columnOrderModel and onColumnOrderModelChange. The issue is that onColumnOrderChange fires while the user is dragging across other columns, not after they let go of the drag.

I am saving datagrid state with an api, not local storage, so i can't use onColumnOrderModelChange to call exportState and save it, not even with debouncing. This has been a frustrating experience, as i have been saving filter/sort/pagination models to our api's to remember ui grid state. I have extensive wrapper around the data-grid and am trying to add controlled column order, but its an incredibly error prone process if i dont want to call my api too much

Edit: And using intialState + restoreState + key prop are a no-go, I have a hard enough time reminding devs to use renderCell option correctly and many other performance issues. Im trying to unmount and remount the data grid as little as possible because it slows everything else down when i don't

dennykoch commented 1 year ago

I'm having the same problem right now. exportState gave me problems in the past (not every state i needed was included and reinitialising felt inconsistent), so I switched to wiring every single part of the state myself. Now I'am stuck because columnOrder is not a fully controlled state. I could implement it myself by manipulating colDefs, but this introduces a kind of "chicken and egg" problem where I first need all the colDefs and than would have to reorder them. This feels not very clean.

konrazem commented 1 year ago

I have custom dialog to restore columns settings saved in localStorage. I am looking for method like current.setColumnsOrderedField(config.columns.orderedFields). I cannot use method current.setState

itsjaked commented 1 year ago

I agree this is important. Our implementation is getting a bit crazy having to hack together the state management. We allow users to create columns, change the initial state, etc. Everything is saved after they take the action (a separate "Save State" button is too clunky, but would make implementation somewhat easier).

skye-levit commented 10 months ago

Any updates on the issue?

ben-gryps commented 5 months ago

I am having a similar issue. I would like to control the column order in the grid through an external component and have them both be in sync.

destegabry commented 2 months ago

I also need to control the order of the columns, or at least be able to rely on initialState.columns.orderedFields (which seems ignored by @mui/x-data-grid-premium": "^7.1.0"

mparsakia commented 1 week ago

The datagrid ignores, or does not process properly the orderedFields when the initial state contains pinnedColumns.left or right, which causes bugs when trying to setup a state restoration by using the initialState prop, data can show up in the wrong "pinned" column that was restored.