Sticky Row Pinning broken when row virtualization is enabled
material-react-table version
v3.0.1
react & react-dom versions
18.3.1
Describe the bug and the steps to reproduce it
When row virtualization is enabled, sticky row pinning does not work. As soon as I disable rowVirtualization or change the rowPinningDisplayMode to something else, it works again.
Minimal, Reproducible Example - (Optional, but Recommended)
const tableConfig: MRT_TableOptions<{ id: number }> = {
data: Array(100).fill({ id: 'id' }).map((_, id) => ({ id })),
columns: [
{
id: 'id',
header: 'ID',
accessorKey: 'id',
},
],
getRowId: (row) => row.id.toString(),
enableRowVirtualization: true,
enableRowPinning: true,
rowPinningDisplayMode: 'sticky',
enablePagination: false,
enableStickyHeader: true,
initialState: {
rowPinning: {
top: ['0'],
bottom: [],
},
},
};
const table = useMaterialReactTable(tableConfig);
return <MaterialReactTable table={table} />;
Screenshots or Videos (Optional)
Do you intend to try to help solve this bug with your own PR?
Maybe, I'll investigate and start debugging
Terms
- [X] I understand that if my bug cannot be reliably reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
yeah, this is unfortunately a known bug without a solution yet. Virtualization is only compatible with about half of the MRT features right now.
yeah, this is unfortunately a known bug without a solution yet. Virtualization is only compatible with about half of the MRT features right now.
Oh okay. Could you provide a full list of supported & unsupported features when virtualization is enabled?
@KevinVandy @TobiasSenger with row virtualization enabled (but column virtualization disabled) I managed to achieve the same behavior by setting rowPinningDisplayMode: 'select-top'.
@KevinVandy an easy fix could be falling back to 'select-top' if row virtualization is enabled. I don't know if it would be acceptable.
const table = useMaterialReactTable({
columns,
data,
editDisplayMode: 'cell',
enableEditing: true,
state: {
isLoading,
columnFilters,
columnFilterFns,
columnPinning,
columnSizing,
grouping,
rowSelection,
expanded,
columnVisibility,
density,
globalFilter,
showColumnFilters,
showGlobalFilter,
sorting,
},
defaultDisplayColumn: { enableResizing: true },
mrtTheme: {
baseBackgroundColor: theme.palette.background.default,
},
muiTablePaperProps: {
sx: {
height: '100%',
display: 'flex',
flexDirection: 'column',
},
},
muiTableBodyCellProps: ({ cell, column, table }) => ({
onKeyDown: (event) => {
if (event.key === 'Enter') {
table.setEditingCell(cell)
queueMicrotask(() => {
const textField =
table.refs.editInputRefs.current?.[column.id]
if (textField) {
textField.focus()
textField.select?.()
}
})
}
},
}),
enableGrouping: true,
enableMultiSort: true,
enablePagination: false,
enableGlobalFilterModes: true,
enableFacetedValues: true,
enableColumnResizing: true,
enableColumnVirtualization: false,
enableColumnPinning: true,
enableColumnFilterModes: true,
enableRowNumbers: false,
enableRowSelection: true,
enableBatchRowSelection: true,
enableRowVirtualization: true,
enableRowPinning: true,
rowPinningDisplayMode: 'select-top',
rowVirtualizerInstanceRef,
rowVirtualizerOptions: { overscan: 10 },
enableTableFooter: false,
enableStickyFooter: false,
enableStickyHeader: true,
enableBottomToolbar: true,
enableTopToolbar: true,
enableKeyboardShortcuts: true,
layoutMode: 'grid-no-grow',
onColumnFiltersChange: (columnFiltersState) => {
const columnFiltersStateFunction = columnFiltersState as (
old: MRT_ColumnFiltersState
) => MRT_ColumnFiltersState
const newColumnFilters = columnFiltersStateFunction(
columnFilters
).map(({ id, value }) => {
if (!Array.isArray(value)) {
return { id, value }
} else
return {
id,
value: value.map((item) => item ?? ''),
}
})
setColumnFilters(newColumnFilters)
},
onColumnFilterFnsChange: setColumnFilterFns,
onColumnPinningChange: setColumnPinning,
onColumnSizingChange: setColumnSizing,
onGroupingChange: setGrouping,
onRowSelectionChange: setRowSelection,
onExpandedChange: setExpanded,
onColumnVisibilityChange: setColumnVisibility,
onDensityChange: setDensity,
onGlobalFilterChange: setGlobalFilter,
onShowColumnFiltersChange: setShowColumnFilters,
onShowGlobalFilterChange: setShowGlobalFilter,
onSortingChange: setSorting,
renderToolbarInternalActions: ({ table }) => (
<Box>
<MRT_ToggleGlobalFilterButton table={table} />
<MRT_ToggleFiltersButton table={table} />
<MRT_ShowHideColumnsButton table={table} />
<MRT_ToggleDensePaddingButton table={table} />
<MRT_ToggleFullScreenButton table={table} />
<ResetMenuButton confirm={confirm} storageKey={storageKey} />
</Box>
),
})