如何在@mui/x-data-grid-pro中固定DetailsPanel?
固定MUI X DataGrid Pro的DetailsPanel(横向滚动不移动)
问题原因
直接给DetailsPanel容器加position: sticky无效,是因为默认的DetailsPanel嵌套在行容器内部,它的定位基准是行而非表格的横向滚动容器,导致无法跟随滚动固定位置。
实现方案
通过自定义DOM结构,将DetailsPanel脱离行嵌套,独立渲染为固定容器,同步行的展开状态和高度:
- 禁用默认DetailsPanel渲染:通过
detailPanel属性返回null,避免内置的嵌套结构。 - 独立固定容器:在DataGrid外部创建一个sticky定位的容器,仅当行展开时显示。
- 同步行状态与布局:监听行的展开/折叠事件,控制固定容器的显示、高度,并给表格行留出左侧空间。
代码示例
import * as React from 'react'; import { DataGridPro, GridRowParams, GridApiRef, useGridApiRef } from '@mui/x-data-grid-pro'; import { Box } from '@mui/material'; // 模拟数据 const rows = Array.from({ length: 10 }).map((_, i) => ({ id: `${i}`, col1: `内容 ${i}`, col2: `长内容 ${i} 重复重复重复重复重复重复重复重复重复重复`, col3: `更多内容 ${i}`, col4: `额外内容 ${i}`, col5: `补充内容 ${i}`, })); const columns = [ { field: 'col1', headerName: '列1', width: 150 }, { field: 'col2', headerName: '列2', width: 300 }, { field: 'col3', headerName: '列3', width: 150 }, { field: 'col4', headerName: '列4', width: 150 }, { field: 'col5', headerName: '列5', width: 150 }, ]; export default function StickyDetailPanelDemo() { const apiRef = useGridApiRef(); const [expandedRowId, setExpandedRowId] = React.useState<string | null>(null); const [panelHeight, setPanelHeight] = React.useState(0); const handleRowExpand = (params: GridRowParams) => { setExpandedRowId(params.id); // 通过API获取行的实际高度 const rowElement = apiRef.current.getRowElement(params.id); if (rowElement) { setPanelHeight(rowElement.offsetHeight); } }; const handleRowCollapse = () => { setExpandedRowId(null); setPanelHeight(0); }; return ( <Box style={{ position: 'relative', width: '100%', overflowX: 'auto' }}> {/* 固定的详情面板 */} {expandedRowId && ( <Box sx={{ position: 'sticky', left: 0, top: 0, height: panelHeight, bgcolor: 'background.paper', zIndex: 10, borderRight: 1, borderColor: 'divider', p: 2, display: 'flex', flexDirection: 'column', justifyContent: 'center', }} > <h4>行 {expandedRowId} 详情</h4> <p>这是固定的详情内容,横向滚动时不会跟随表格移动</p> <p>可以在这里添加任意自定义内容</p> </Box> )} <DataGridPro apiRef={apiRef} rows={rows} columns={columns} detailPanel={() => null} // 禁用默认详情面板 onRowExpand={handleRowExpand} onRowCollapse={handleRowCollapse} sx={{ '& .MuiDataGrid-row': { // 给固定面板留出左侧空间 paddingLeft: expandedRowId ? '280px' : 0, transition: 'padding-left 0.2s', }, '& .MuiDataGrid-cell': { borderRight: '1px solid rgba(224, 224, 224, 1)', }, }} initialState={{ pagination: { paginationModel: { pageSize: 5 } }, }} /> </Box> ); }
关键细节
- 该方案在社区版(@mui/x-data-grid)也能生效,无需依赖Pro版即可验证功能。
- 通过
useGridApiRef可以精准获取行的DOM元素和高度,替代模拟值。 - 若需支持多行展开,可扩展状态管理逻辑,为每个展开的行创建独立的固定面板。
内容的提问来源于stack exchange,提问作者isimisi
相关产品推荐
相关产品推荐

