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/
4.14k stars 1.29k forks source link

[data grid] All grouped rows collapses when rows updating (by state, not by updateRows) #13064

Open iOrcohen opened 5 months ago

iOrcohen commented 5 months ago

Steps to reproduce

Link to live example: code sandbox

Steps:

  1. Expand one or more of the groups.
  2. Click on one of the buttons - update row, update rows, delete row or add row.
  3. All the groups collapses.

Current behavior

All groups collapses after the rows state changed.

Expected behavior

Groups expansion won't be effected by the rows change.

Context

We update the table rows with fresh data every one minute in our application (It's include coins prices data which require often refresh). After every refresh all the groups collapses automatically, which make unpleasant user experience.

Your environment

npx @mui/envinfo ``` System: OS: macOS 14.4.1 Binaries: Node: 18.16.0 - /usr/local/bin/node npm: 9.5.1 - /usr/local/bin/npm pnpm: Not Found Browsers: Chrome: 124.0.6367.119 Edge: Not Found Safari: 17.4.1 npmPackages: @emotion/react: ^11.11.4 => 11.11.4 @emotion/styled: ^11.11.0 => 11.11.0 @mui/base: 5.0.0-beta.28 @mui/core-downloads-tracker: 5.15.14 @mui/lab: ^5.0.0-alpha.127 => 5.0.0-alpha.157 @mui/material: ^5.15.14 => 5.15.14 @mui/private-theming: 5.15.14 @mui/styled-engine: 5.15.14 @mui/system: 5.15.14 @mui/types: 7.2.14 @mui/utils: 5.15.14 @mui/x-data-grid: 6.19.11 @mui/x-data-grid-premium: ^6.19.11 => 6.19.11 @mui/x-data-grid-pro: 6.19.11 @mui/x-date-pickers: ^6.10.2 => 6.18.5 @mui/x-date-pickers-pro: ^6.18.0 => 6.18.5 @mui/x-license-pro: 6.10.2 @types/react: 18.2.45 react: ^18.2.0 => 18.2.0 react-dom: ^18.2.0 => 18.2.0 typescript: ^4.9.5 => 4.9.5 ```

Search keywords: expansion, grouping Order ID: 66471 + 90144

michelengelen commented 5 months ago

Hey @iOrcohen ... thanks for opening this ticket. The behavior you are describing is actually to be expected. Since re-rendering the complete data grid on every state change it will re-render with the initialState and the collapsed rows. This can be prevented when using the updateRows method from the apiRef or, if this is not an option, you can always create a custom state and function for isGroupExpandedByDefault. This is from the group expansion part of the docs.

@cherniavskii is there any plan of including the row-expansion state in the grid state?

iOrcohen commented 5 months ago

@michelengelen Thanks for your comment! We will try solve it by using the updateRows function, but since the common usage of the rows change is by changing the state, I think the row expansion should be part of the grid state, and remain the same from render to render as same as filtering, grouping and all the others.

If the plan is to the add the row-expansion to the grid state, let me know and I might contribute it myself :)

Thanks again.

michelengelen commented 5 months ago

I did add this to the board. 👍🏼

iOrcohen commented 5 months ago

@michelengelen I'm sorry but just for clarification, does it mean this feature is in the roadmap? Is there any estimation if so? I'm trying to think if I should manage the updateRows solution in the meanwhile.

Thanks again!

michelengelen commented 5 months ago

@michelengelen I'm sorry but just for clarification, does it mean this feature is in the roadmap?

Is there any estimation if so?

I'm trying to think if I should manage the updateRows solution in the meanwhile.

Thanks again!

It is currently not planned as part of the roadmap. Adding it to the board is the first step of starting a discussion about it and eventually coming up with a fast solution.

cherniavskii commented 5 months ago

Related discussion: https://github.com/mui/mui-x/issues/7771

We might reconsider the default behavior for the next major since the current behavior is clearly confusing to many users.

SamJB123 commented 4 months ago

Hi all

I've developed a band-aid solution to this, leveraging (a) the internal state's storage of whether rows belonging to a group are visible pre-update and (b) the fact that group rows can be dynamically identified by their prefix.

Sharing in case it helps anybody else, as this was driving me nuts!

Initialise a dynamic state for expanded row groups

    const [expandedGroups, setExpandedGroups] = useState<string[]>([]);

...

The main function

  const HandleNodeClick_withSavedExpandState = useCallback(
    debounce((node) => {
      // Get current apiRef state
      const CurrentGridState = apiRef.current.state;

      // Dynamically identify the group headings that are currently visible by using the visibleRowsLookup object, and the fact that group headings start with "auto-generated-row-type/"
      const visibleGroups = Object.keys(CurrentGridState.visibleRowsLookup).filter(row => row.startsWith('auto-generated-row-type/'));

      // Store the identified group headings for reference
      const visibleGroupsWithoutPrefix = visibleGroups.map(row => row.replace('auto-generated-row-type/', ''));

      // To check if each group is currently expanded, check if the first row of each group is visible
      const firstRowOfEachGroup = visibleGroups.map(groupId => 
        apiRef.current.getRowGroupChildren({groupId})[0]
      );      
      const firstRowVisibility = firstRowOfEachGroup.map(row => CurrentGridState.visibleRowsLookup[row]);

      // Build an array of the visible groups (without prefix), based on those for which which the first row is visible
      const visibleExpandedGroups = visibleGroupsWithoutPrefix.filter((_, index) => firstRowVisibility[index]);
      console.log('Visible Expanded Groups: ', visibleExpandedGroups);

      // Pass this array of expanded groups to the state for the next render
      setExpandedGroups(visibleExpandedGroups);

      // Call the original trigger for a state update
      originalHandleNodeClick(node);

    }, 300),
    []
  );

...

Define the 'isGroupExpandedByDefault' parameter dynamically

  const isGroupExpandedByDefault = useCallback((node: GridGroupNode) =>
    node.groupingField === '[YOUR_GROUP_FIELD_NAME_HERE]' && expandedGroups.includes(String(node.groupingKey)), [expandedGroups]);

...

Include the parameter in your DataGrid output

    <DataGridPremium
        isGroupExpandedByDefault={isGroupExpandedByDefault} />
tunganh-phamba commented 3 months ago

I am also experiencing this bug and it significantly impacts my work. It would be greatly appreciated if a fix could be provided soon. Thank you for your attention to this matter.

kseileraltus commented 3 months ago

Thanks Sam for the workaround! For what its worth, I would also greatly appreciate official support to keep the rows expanded on interaction.

tonynchen commented 2 months ago

Hi team, we are also experiencing this issue, and would appreciate the fix.

Order Number: 77799

Thanks!

Matthieudegny commented 1 month ago

Hey,

I'm also experiencing the bug. I would really appreciate it if you could fix it.

Thanks