material-react-table icon indicating copy to clipboard operation
material-react-table copied to clipboard

Sticky Row Pinning broken when row virtualization is enabled

Open TobiasSenger opened this issue 1 year ago • 3 comments

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)

image image image image

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.

TobiasSenger avatar Nov 21 '24 07:11 TobiasSenger

yeah, this is unfortunately a known bug without a solution yet. Virtualization is only compatible with about half of the MRT features right now.

KevinVandy avatar Dec 09 '24 04:12 KevinVandy

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?

TobiasSenger avatar Dec 10 '24 07:12 TobiasSenger

@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>
        ),
    })

matteo4diani avatar Apr 03 '25 07:04 matteo4diani