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

[DataGrid] autoheight + maxHeight to limit the displayed rows doesn't work

Open venik2007 opened this issue 3 years ago • 14 comments
trafficstars

Summary 💡

I need to have a data grid embedded into some Summary Page content. So before and after the <DataGrid> component I have some data. The <DataGrid> should be flexible (empty DataGrid looks not good enough in my case) and for 1 row should be small (like it already happens when autosize is switched on). But for more than 5 rows (for ex.) I need to prevent further <DataGrid> stretching to keep the rest content visible.

Examples 🌈

Here is an example https://codesandbox.io/s/autoheightgrid-material-demo-forked-r48po?file=/demo.tsx.

https://github.com/user-attachments/assets/3c3d014a-3d63-4580-9dd9-4786b14ca3e3

In that example, I've met really close implementation to what I want, but unfortunately, datagrid header and footer stay unpinned and disappear on scrolling. But I need behavior like DataGrid without autoheight with specified height. Is it possible to solve my problem somehow with the current functionality?

Motivation 🔦

I'm totally ok with:

  • displayed rows quantity limit (maxRowsDisplayed or something like that)
  • pinned DataGrid's header/footer (through MuiThemes, if it will not break anything in DataGrid virtualization)
  • etc.

Order ID 💳 (optional)

No response

venik2007 avatar Dec 30 '21 15:12 venik2007

Setting a maxHeight currently has no effect on the grid, so you need to use height. To avoid showing an empty space when there's no row or only a few rows, you can programmatically change the container height to auto and enable autoHeight. There're two scenarios to cover:

The number of rows will exceed the available space:

<div style={{ height: 300, overflow: "auto" }}>
  <DataGrid autoHeight={false} />
</div>

The number of rows will not exceed the available space:

<div style={{ height: 'auto', overflow: "auto" }}>
  <DataGrid autoHeight={true} />
</div>

Does it solve your case?

m4theushw avatar Dec 30 '21 18:12 m4theushw

Thank you for your answer @m4theushw , but no, unfortunately it doesn't cover my case. Let me describe my case in that way: I have a div with specific maxHeight and maxWidth values and i need from table to fill this div, but don't leave this div's boundaries. So for autosize === true i want to see that grid header will reach out (pin) top border of parent div, and grid footer (pagination, rows quantity etc.) will reach out (pin) bottom border of parent div, without any cuttings and only rows will be scrolled in that grid (but not header/footer). Exactly like it works for parent with defined height when autoHeight === false.

Let me provide some examples which looks bad in my project (when autoHeight === true and wrapped with specific parent's height): image or image

venik2007 avatar Jan 12 '22 16:01 venik2007

What I would recommend is to not use the autoHeight feature. It was not introduced to cover your use case. Instead, you can set the height of the data grid's parent based on the size of your data set.

oliviertassinari avatar Jan 29 '22 19:01 oliviertassinari

Try this:

rows per page const rpp = 8

and on parent container style={{height: 108 + (rpp * 52) + 'px'}}

and Datagrid prop pageSize={rpp}

matintrenta avatar May 16 '22 19:05 matintrenta

Not so good if there are less than rpp rows in your dataset.

Try this... style={{ height: 108 + Math.min(rpp, items.length) * 52 + 'px' }}

nickraphael avatar Jul 13 '22 06:07 nickraphael

Mine was like this height: 'calc(100vh - 280px)' (In this case, the 280px is my header)

GuilhermeMelati avatar Dec 04 '22 13:12 GuilhermeMelati

=> afterstruggling for a while finally this works for me like a magic:

<Box id="DataGridContainer" sx={{height: '52vw', width: '94vw'}}> <Box sx={{height: '100% !important', width: "100% !important"}}>

<DataGrid disableSelectionOnClick sx={{height: 'inherit !important', width: "inherit"}} rows={rows} columns={cols} />

</Box> </Box>

now I have complete control over the width and height through the top level box #DataGridContainer

note: Box are from Mui elements MUI version used: "@mui/material": "^5.11.8", "@mui/x-data-grid": "^5.11.0",

ahmed-zhran avatar Apr 07 '23 22:04 ahmed-zhran

I managed to get this working, though I had to use some pretty hacky css selectors in the SX. Height is controlled by the parent Box

<Box sx={{ maxHeight: 'calc(100vh - 360px)' }}>
  <DataGrid
    autoHeight={true}
    sx={{
      overflow: 'auto',
      '.MuiDataGrid-virtualScroller': {
        height: 'auto',
        overflow: 'hidden',
      },
      '.MuiDataGrid-main > div:nth-child(2)': {
        overflowY: 'auto !important',
        flex: 'unset !important',
      },
    }}
    treeData
  />
</Box>

tomhalley avatar Apr 28 '23 11:04 tomhalley

am i the only one who finds these "styling" solutions abysmal?

jpodpro avatar Sep 25 '23 21:09 jpodpro

Hi! Is there a solution that works with tree data as well? In this case the number of visible rows can change, so it's not enough to simply count all rows. Is there a way to get the number of visible (parent / child) rows before they are rendered?

It would be great if MUI DataGrid had a maxHeight option, which would work like autoHeight only up to a specific height (e.g. height of the viewport) to be able to use row virtualization when number of rows is high.

EDIT: Veeery early version of an experiment to make it work with tree data and fixed row height:

const useAutoMaxHeight = ({
  api,
  rowHeight,
}: {
  api: GridApiPro
  rowHeight: number
}) => {
  const [isAutoHeightEnabled, setIsAutoHeightEnabled] = React.useState(true)

  useEffect(() => {
    if (api.subscribeEvent && api.state && api.instanceId) {
      return api.subscribeEvent('stateChange', () => {
        const visibleRowIds = gridExpandedSortedRowIdsSelector(
          api.state,
          api.instanceId,
        )

        // Table height without header and pinned rows
        const tableHeight = rowHeight * visibleRowIds.length
        const viewportHeight = window.innerHeight

        setIsAutoHeightEnabled(tableHeight < viewportHeight)
      })
    }
  }, [api, rowHeight])

  return isAutoHeightEnabled
}

export const MyDataGrid = (props) => {
  const apiRef = useGridApiRef()

  const isAutoHeightEnabled = useAutoMaxHeight({
    api: apiRef.current,
    rowHeight: props.rowHeight,
  })

  return (
    <div
      style={{
        height: isAutoHeightEnabled ? 'auto' : '100vh',
        overflow: 'auto',
      }}
    >
      <DataGridPro
        apiRef={apiRef}
        autoHeight={isAutoHeightEnabled}
        ...
      />
    </div>
  )
}

szymonnowak-st avatar Nov 17 '23 18:11 szymonnowak-st

Other workaround can be:

<DataGrid
          autoHeight={true}
          sx={{
            '.MuiDataGrid-virtualScroller': {
              overflowY: 'auto !important',
              // example of maxHeight
              maxHeight: 'calc(100vh - 100px) !important',
            },
          }}
    ...otherProps
/>

ezequielgalardi avatar Jan 26 '24 19:01 ezequielgalardi

I have a similar use-case to this issue, where I have a page containing several DataGrids that I want to have a maximum height, but also shrink to a smaller height if needed.

Previously, in x-data-grid 6.x, I was able to solve this with a flexbox container with a max-height. For example:

      <Box
        sx={{
          display: 'flex',
          flexDirection: 'column',
          maxHeight: '400px',
        }}
      >
        <DataGrid rows={rows} columns={columns} />
      </Box>

However, upon upgrading to x-data-grid 7.x, this stopped working (the DataGrid sizes correctly, but scrolling doesn't work).

  • Example using 6.x, which works: https://stackblitz.com/edit/react-v9w8tw-dnxxrf?file=Demo.tsx
  • Example using 7.x, which has broken scrolling: https://stackblitz.com/edit/react-v9w8tw?file=Demo.tsx

Based on the age of this issue, the discussion in comments around programmatic sizing or hard-coded style workarounds, and also the callout in these docs: https://mui.com/x/react-data-grid/layout/

By default, the Data Grid has no intrinsic dimensions. Instead, it takes up the space given by its parent. The Data Grid will raise an error in the console if its container has no intrinsic dimensions.

...I'm starting to think that the CSS-only flexbox solution I was using wasn't officially supported.

Would someone be able to confirm this?

I thought about opening a new issue, but it seemed like it was going to be a duplicate of this one.

greglittlefield-wf avatar Aug 27 '24 21:08 greglittlefield-wf

Hey @greglittlefield-wf! I'm here to help you with any bugs, questions, or becoming a contributor. Let's squash those bugs together! 🤖

Yes, the CSS-only flexbox solution for setting a maximum height and allowing shrinkage of a DataGrid in x-data-grid 6.x is officially unsupported in x-data-grid 7.x. You should use the autoHeight prop instead.

Supporting evidence from the document:

/**
 * If `true`, the Data Grid height is dynamic and follows the number of rows in the Data Grid.
 * @default false
 */
autoHeight: PropTypes.bool,

Additionally, the autoHeight prop is designed to handle dynamic height adjustments, making it the recommended approach for achieving the desired behavior in x-data-grid 7.x [1][2].

To continue talking to Dosu, mention @dosu.

dosubot[bot] avatar Aug 27 '24 21:08 dosubot[bot]

@greglittlefield-wf Yeah, this looks like a regression.

  • [ ] 1. Doing this diff fixes it for me.
diff --git a/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx b/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx
index 8fcbd0a41..c8b4ca5e3 100644
--- a/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx
+++ b/packages/x-data-grid/src/components/virtualization/GridMainContainer.tsx
@@ -20,6 +20,8 @@ const Element = styled('div', {
   flexGrow: 1,
   position: 'relative',
   overflow: 'hidden',
+  display: 'flex',
+  flexDirection: 'column',
 });

 export const GridMainContainer = React.forwardRef<
  1. And then, I guess the solution to this issue is simple:
      <div style={{ maxHeight: 300, display: "flex", flexDirection: "column" }}>
        <DataGrid {...data} rows={data.rows.slice(0, nbRows)} />
      </div>

https://github.com/user-attachments/assets/f029379f-e024-4a2d-964c-bddd1013f451

https://codesandbox.io/p/sandbox/autoheightgrid-material-demo-forked-c6f8pn?workspaceId=836800c1-9711-491c-a89b-3ac24cbd8cd8

  • [ ] 3. This can go as a new demo in https://mui.com/x/react-data-grid/layout/

oliviertassinari avatar Aug 27 '24 23:08 oliviertassinari

@oliviertassinari When should we expect item 1 from solution above to be fixed and released? Also this doesn't work for virtualized data grid (i.e. DataGridPro) - when you remove a row, the data grid doesn't shrink and it stays the same height. I tried adding autoHeight prop, it works in terms of adjusting the height properly but scrollbar disappears

dimon82 avatar Sep 05 '24 00:09 dimon82

When should we expect item 1 from solution above to be fixed and released?

@dimon82 I don't know, I guess when someone opens a PR to apply this fix. But I would imagine that we don't do 1. without 3. We might be waiting on more upvotes.

this doesn't work for virtualized data grid (i.e. DataGridPro) - when you remove a row, the data grid doesn't shrink and it stays the same height. I tried adding autoHeight prop, it works in terms of adjusting the height properly but scrollbar disappears

I can't reproduce this issue with the above diff applied.

oliviertassinari avatar Sep 05 '24 00:09 oliviertassinari

@oliviertassinari actually doesn't even have to be virtualized, regular paginated data grid is not working either. Try to decrease the number of columns so there is no horizontal scrollbar and it won't shrink when rows are removed:

https://codesandbox.io/p/sandbox/autoheightgrid-material-demo-forked-mlw8hf?file=%2Fdemo.tsx%3A14%2C18

then try adding autoHeight to DataGrid, this is how I want it to behave in terms of changing height when the number of rows changes (up to a maxHeight). But since it removes vertical scrollbar, this doesn't really solve it

also since diff is a part of mui package, how would I apply it in my code? just override styles for .MuiDataGrid-main?

dimon82 avatar Sep 05 '24 17:09 dimon82

@dimon82 Right, I should have updated the codesandbox linked in https://github.com/mui/mui-x/issues/3524#issuecomment-2313727955 to demonstrate the diff. This is now done, it should work.

oliviertassinari avatar Sep 05 '24 19:09 oliviertassinari

@oliviertassinari this only fixes vertical scroll, but still doesn't fix the problem of height being adjusted when you remove rows when there is no horizontal scrollbar (less columns), see below, try to remove rows

https://codesandbox.io/p/sandbox/autoheightgrid-material-demo-forked-m2vnq3

dimon82 avatar Sep 05 '24 20:09 dimon82

@dimon82 Interesting, so https://github.com/mui/mui-x/issues/3524#issuecomment-2313727955 is only fixing v7 regression, but not this issue.

It looks like that when there is no horizontal scrollbar (not enough columns), then the gridClasses.filler element takes the remaining space.

oliviertassinari avatar Sep 05 '24 22:09 oliviertassinari

Interesting, I was not aware this was possible in v6: https://stackblitz.com/edit/react-v9w8tw-55hdpw?file=Demo.tsx It seems to solve the same issue I was trying to solve with conditional autoHeight in https://github.com/mui/mui-x/pull/9274 It would be great to make this possible again in v7, I'll look into it 👍🏻

cherniavskii avatar Sep 11 '24 21:09 cherniavskii

This issue has been closed. If you have a similar problem but not exactly the same, please open a new issue. Now, if you have additional information related to this issue or things that could help future readers, feel free to leave a comment.

[!NOTE] We value your feedback @venik2007! How was your experience with our support team? We'd love to hear your thoughts in this brief Support Satisfaction survey. Your insights help us improve!

github-actions[bot] avatar Sep 25 '24 07:09 github-actions[bot]