Skip to content

Commit

Permalink
[DataGrid] Support column virtualization with dynamic row height (#15541
Browse files Browse the repository at this point in the history
)
  • Loading branch information
cherniavskii authored Nov 23, 2024
1 parent 419eb67 commit 00c0b2b
Show file tree
Hide file tree
Showing 18 changed files with 188 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';

function useData(rowLength, columnLength) {
const [data, setData] = React.useState({ columns: [], rows: [] });

React.useEffect(() => {
const rows = [];

for (let i = 0; i < rowLength; i += 1) {
const row = {
id: i,
};

for (let j = 1; j <= columnLength; j += 1) {
row[`price${j}M`] = `${i.toString()}, ${j} `;
}

rows.push(row);
}

const columns = [];

for (let j = 1; j <= columnLength; j += 1) {
columns.push({ field: `price${j}M`, headerName: `${j}M`, width: 55 });
}

setData({
rows,
columns,
});
}, [rowLength, columnLength]);

return data;
}

export default function VirtualizeColumnsWithAutoRowHeight() {
const data = useData(100, 100);

return (
<div style={{ height: 600, width: '100%' }}>
<DataGrid
{...data}
getRowHeight={() => 'auto'}
virtualizeColumnsWithAutoRowHeight
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from 'react';
import { DataGrid, GridColDef, GridRowId } from '@mui/x-data-grid';

export interface DataRowModel {
id: GridRowId;
[price: string]: number | string;
}

export interface GridData {
columns: GridColDef[];
rows: DataRowModel[];
}

function useData(rowLength: number, columnLength: number) {
const [data, setData] = React.useState<GridData>({ columns: [], rows: [] });

React.useEffect(() => {
const rows: DataRowModel[] = [];

for (let i = 0; i < rowLength; i += 1) {
const row: DataRowModel = {
id: i,
};

for (let j = 1; j <= columnLength; j += 1) {
row[`price${j}M`] = `${i.toString()}, ${j} `;
}

rows.push(row);
}

const columns: GridColDef[] = [];

for (let j = 1; j <= columnLength; j += 1) {
columns.push({ field: `price${j}M`, headerName: `${j}M`, width: 55 });
}

setData({
rows,
columns,
});
}, [rowLength, columnLength]);

return data;
}

export default function VirtualizeColumnsWithAutoRowHeight() {
const data = useData(100, 100);

return (
<div style={{ height: 600, width: '100%' }}>
<DataGrid
{...data}
getRowHeight={() => 'auto'}
virtualizeColumnsWithAutoRowHeight
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<DataGrid
{...data}
getRowHeight={() => 'auto'}
virtualizeColumnsWithAutoRowHeight
/>
12 changes: 11 additions & 1 deletion docs/data/data-grid/row-height/row-height.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ This side effect happens because a row height estimation is used while a row is
You can configure the estimated value used by passing a function to the `getEstimatedRowHeight` prop.
If not provided, the default row height of `52px` is used as estimation.
It's recommended to pass this prop if the content deviates too much from the default value.
Note that, due to the implementation adopted, the virtualization of the columns is also disabled to force all columns to be rendered at the same time.

```tsx
<DataGrid getRowHeight={() => 'auto'} getEstimatedRowHeight={() => 200} />
Expand All @@ -78,6 +77,17 @@ Add padding to the cells to increase the space between the content and the cell

:::

### Column virtualization

By default, the virtualization of the columns is disabled to force all columns to be rendered at the same time and calculate the row height correctly.
However, this can lead to poor performance when rendering a lot of columns.

If you need column virtualization, you can set the `virtualizeColumnsWithAutoRowHeight` prop to `true`.
With this approach, the Data Grid measures the row height based on the visible columns.
However, the row height might change during horizontal scrolling.

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

## Row density

Give your users the option to change the default row density to match their preferences—compact, standard, or comfortable.
Expand Down
7 changes: 6 additions & 1 deletion docs/data/data-grid/virtualization/virtualization.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ By default, columns coming under 150 pixels region are rendered outside of the v

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

You can disable column virtualization by calling `apiRef.current.unstable_setColumnVirtualization(false)`, or by setting the column buffer to the number of total columns.
You can disable column virtualization by calling `apiRef.current.unstable_setColumnVirtualization(false)`, or by setting the [`columnBufferPx`](/x/api/data-grid/data-grid/#data-grid-prop-columnBufferPx) to a high value.

:::info
Column virtualization is disabled when dynamic row height is enabled.
See [dynamic row height and column virtualization](/x/react-data-grid/row-height/#column-virtualization) to learn more.
:::

## Disable virtualization

Expand Down
3 changes: 2 additions & 1 deletion docs/pages/x/api/data-grid/data-grid-premium.json
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,8 @@
}
},
"unstable_listView": { "type": { "name": "bool" } },
"unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" }
"unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" },
"virtualizeColumnsWithAutoRowHeight": { "type": { "name": "bool" }, "default": "false" }
},
"name": "DataGridPremium",
"imports": [
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/x/api/data-grid/data-grid-pro.json
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,8 @@
}
},
"unstable_listView": { "type": { "name": "bool" } },
"unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" }
"unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" },
"virtualizeColumnsWithAutoRowHeight": { "type": { "name": "bool" }, "default": "false" }
},
"name": "DataGridPro",
"imports": [
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/x/api/data-grid/data-grid.json
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,8 @@
},
"additionalInfo": { "sx": true }
},
"unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" }
"unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" },
"virtualizeColumnsWithAutoRowHeight": { "type": { "name": "bool" }, "default": "false" }
},
"name": "DataGrid",
"imports": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,9 @@
},
"unstable_rowSpanning": {
"description": "If <code>true</code>, the Data Grid will auto span the cells over the rows having the same value."
},
"virtualizeColumnsWithAutoRowHeight": {
"description": "If <code>true</code>, the Data Grid enables column virtualization when <code>getRowHeight</code> is set to <code>() =&gt; &#39;auto&#39;</code>. By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly. For datasets with a large number of columns, this can cause performance issues. The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally."
}
},
"classDescriptions": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,9 @@
},
"unstable_rowSpanning": {
"description": "If <code>true</code>, the Data Grid will auto span the cells over the rows having the same value."
},
"virtualizeColumnsWithAutoRowHeight": {
"description": "If <code>true</code>, the Data Grid enables column virtualization when <code>getRowHeight</code> is set to <code>() =&gt; &#39;auto&#39;</code>. By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly. For datasets with a large number of columns, this can cause performance issues. The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally."
}
},
"classDescriptions": {
Expand Down
3 changes: 3 additions & 0 deletions docs/translations/api-docs/data-grid/data-grid/data-grid.json
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,9 @@
},
"unstable_rowSpanning": {
"description": "If <code>true</code>, the Data Grid will auto span the cells over the rows having the same value."
},
"virtualizeColumnsWithAutoRowHeight": {
"description": "If <code>true</code>, the Data Grid enables column virtualization when <code>getRowHeight</code> is set to <code>() =&gt; &#39;auto&#39;</code>. By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly. For datasets with a large number of columns, this can cause performance issues. The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally."
}
},
"classDescriptions": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,14 @@ DataGridPremiumRaw.propTypes = {
* @default false
*/
unstable_rowSpanning: PropTypes.bool,
/**
* If `true`, the Data Grid enables column virtualization when `getRowHeight` is set to `() => 'auto'`.
* By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly.
* For datasets with a large number of columns, this can cause performance issues.
* The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally.
* @default false
*/
virtualizeColumnsWithAutoRowHeight: PropTypes.bool,
} as any;

interface DataGridPremiumComponent {
Expand Down
8 changes: 8 additions & 0 deletions packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1026,4 +1026,12 @@ DataGridProRaw.propTypes = {
* @default false
*/
unstable_rowSpanning: PropTypes.bool,
/**
* If `true`, the Data Grid enables column virtualization when `getRowHeight` is set to `() => 'auto'`.
* By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly.
* For datasets with a large number of columns, this can cause performance issues.
* The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally.
* @default false
*/
virtualizeColumnsWithAutoRowHeight: PropTypes.bool,
} as any;
8 changes: 8 additions & 0 deletions packages/x-data-grid/src/DataGrid/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -821,4 +821,12 @@ DataGridRaw.propTypes = {
* @default false
*/
unstable_rowSpanning: PropTypes.bool,
/**
* If `true`, the Data Grid enables column virtualization when `getRowHeight` is set to `() => 'auto'`.
* By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly.
* For datasets with a large number of columns, this can cause performance issues.
* The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally.
* @default false
*/
virtualizeColumnsWithAutoRowHeight: PropTypes.bool,
} as any;
1 change: 1 addition & 0 deletions packages/x-data-grid/src/components/cell/GridCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ const GridCell = React.forwardRef<HTMLDivElement, GridCellProps>(function GridCe
padding: 0,
opacity: 0,
width: 0,
height: 0,
border: 0,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ export const DATA_GRID_PROPS_DEFAULT_VALUES: DataGridPropsWithDefaultValues = {
sortingOrder: ['asc' as const, 'desc' as const, null],
throttleRowsMs: 0,
unstable_rowSpanning: false,
virtualizeColumnsWithAutoRowHeight: false,
};
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type {
GridRowEntry,
GridRowId,
} from '../../../models';
import { DataGridProcessedProps } from '../../../models/props/DataGridProps';
import { selectedIdsLookupSelector } from '../rowSelection/gridRowSelectionSelector';
import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector';
import { getFirstNonSpannedColumnToRender } from '../columns/gridColumnsUtils';
Expand Down Expand Up @@ -640,6 +641,7 @@ type RenderContextInputs = {
visibleColumns: ReturnType<typeof gridVisibleColumnDefinitionsSelector>;
hiddenCellsOriginMap: ReturnType<typeof gridRowSpanningHiddenCellsOriginMapSelector>;
listView: boolean;
virtualizeColumnsWithAutoRowHeight: DataGridProcessedProps['virtualizeColumnsWithAutoRowHeight'];
};

function inputsSelector(
Expand Down Expand Up @@ -677,6 +679,7 @@ function inputsSelector(
visibleColumns,
hiddenCellsOriginMap,
listView: rootProps.unstable_listView ?? false,
virtualizeColumnsWithAutoRowHeight: rootProps.virtualizeColumnsWithAutoRowHeight,
};
}

Expand Down Expand Up @@ -740,12 +743,14 @@ function computeRenderContext(
lastSize: inputs.lastRowHeight,
});

for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
const row = inputs.rows[i];
hasRowWithAutoHeight = inputs.apiRef.current.rowHasAutoHeight(row.id);
if (!inputs.virtualizeColumnsWithAutoRowHeight) {
for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
const row = inputs.rows[i];
hasRowWithAutoHeight = inputs.apiRef.current.rowHasAutoHeight(row.id);
}
}

if (!hasRowWithAutoHeight) {
if (!hasRowWithAutoHeight || inputs.virtualizeColumnsWithAutoRowHeight) {
firstColumnIndex = binarySearch(realLeft, inputs.columnPositions, {
atStart: true,
lastPosition: inputs.columnsTotalWidth,
Expand Down
8 changes: 8 additions & 0 deletions packages/x-data-grid/src/models/props/DataGridProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,14 @@ export interface DataGridPropsWithDefaultValues<R extends GridValidRowModel = an
* @default false
*/
unstable_rowSpanning: boolean;
/**
* If `true`, the Data Grid enables column virtualization when `getRowHeight` is set to `() => 'auto'`.
* By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly.
* For datasets with a large number of columns, this can cause performance issues.
* The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally.
* @default false
*/
virtualizeColumnsWithAutoRowHeight: boolean;
}

/**
Expand Down

0 comments on commit 00c0b2b

Please sign in to comment.