Hassan Akhlaq
Hassan Akhlaq

Reputation: 445

Issue Combining Virtualization with Expanding Sub-Rows in Material React Table

First of all, I’d like to express my admiration for this package—it’s incredibly flexible and thoughtfully designed

Recently, I implemented virtualization in one of my projects to handle a large dataset, using the example provided in your documentation: Infinite Scrolling Example. It worked flawlessly—thank you for this excellent guide!

However, my project also requires an expand-collapse functionality for rows. I attempted to combine the virtualization example with the Expanding Sub-Rows Guide. Unfortunately, I’ve encountered an issue where expanding a parent row does not display the sub-rows.

Problem: When I expand a parent row, the sub-rows don’t render correctly in the table.

image

Steps I Followed:

I used the infinite scrolling example to handle large datasets with virtualization. I integrated the expanding sub-rows functionality as described in the guide.

Question: Could you please provide guidance on how to properly combine these two features? Are there any specific adjustments or best practices needed to make them work seamlessly together?

Thank you in advance for your help, and I’m happy to provide additional details or code snippets if needed.

This is what i have so far code wise:

    const { data, fetchNextPage, isError, isFetching, isLoading } = useInfiniteQuery({
    queryKey: ['table-data', columnFilters, expanded, sorting],
    queryFn: async ({ pageParam = 0 }) => {
      const offset = pageParam * fetchSize;
  
      const preQueryFilters = props.preQueryRes.decompose()[0].rawData();
      let response,processedResp;
  
      const expandedRowId = Object.entries(expanded).find(([id, isExpanded]) => isExpanded)?.[0];
  
      if (isTriggeredByExpansion) { //checking if there is a change in expanded state
        console.log('Fetching subRows for expanded row:', expandedRowId);
  
        const id = expandedRowId.split('-').pop(); // Extract the last part of the ID . since i only allow one expansion at a time
        const [subDim,readyQuery] = addSubQueryFilter(props.query, id)
        response = await loadCubeData(readyQuery);
        try{
          processedResp = processData(response,subDim)
          processedResp = [...completeData.current,...processedResp]
        }
        catch(e){
          console.log(e)
        }
      } else {
        console.log('Fetching top-level rows');
        response = await loadCubeData(addPreQueryResAsFilter(props.query, preQueryFilters.slice(offset, offset + fetchSize)));
        try{
          processedResp = processData(response)
          completeData.current=[...completeData.current,...processedResp]
        }
        catch(e){
          console.log(e)
        }
        // completeData.current = processedResp; // Cache top-level data
      }
  
      return {
        data: processedResp,
        meta: { totalRowCount: preQueryFilters.length || 0 },
      };
    },
    initialPageParam: 0,
    getNextPageParam: (_lastGroup, groups) => groups.length,
    refetchOnWindowFocus: false,
     });
 
     const flatReportData = useMemo(() => {
    console.log('my data.....',data)

    const newData = data?.pages?.flatMap((page) => page.data) || [];
    return [...newData];
      }, [data]);
      <MaterialReactTable
            columns={tableColumns.current}
            data={flatReportData.filter((r) => !r.parentId)}
            enablePagination={false}
            enableRowVirtualization
            getRowId={(originalRow) => originalRow.id} // Use the `id` field as the unique identifier
            muiTableContainerProps={{
              ref: tableContainerRef,
              sx: { maxHeight: '600px' },
              onScroll: (event) => fetchMoreOnBottomReached(event.target),
            }}
            muiToolbarAlertBannerProps={isError ? { color: 'error', children: 'Error loading data' } : undefined}
            renderBottomToolbarCustomActions={() => (
              <Typography>
                Fetched {totalFetched} of {totalDBRowCount} total rows.
              </Typography>
            )}
            
            state={{
              expanded,
              columnFilters,
              isLoading,
              showAlertBanner: isError,
              showProgressBars: isFetching,
              sorting,
            }}
            rowVirtualizerInstanceRef={rowVirtualizerInstanceRef}
            rowVirtualizerOptions={{ overscan: 4 }}
            onColumnFiltersChange={setColumnFilters}
            onExpandedChange= {setExpanded}
            enableTopToolbar={false}
            enableExpanding
            getRowCanExpand =  {(row) => {return row.original.level < levels.length}} //just some type of boolean
            getSubRows={ (row) => {
              console.log('row-expanded',row,flatReportData,flatReportData.filter((r) => r.parentId === row.id)) 
              return flatReportData.filter((r) => r.parentId === row.id)
            }}
            onSortingChange={setSorting}
            paginateExpandedRows={false}
            enableColumnFilters={false}
            enableColumnActions={false}
            enableFullScreenToggle={false}
            enableDensityToggle={false}
            initialState={{ density: 'spacious' }}
            enableHiding={false}
           
          />

Upvotes: 1

Views: 180

Answers (1)

Hassan Akhlaq
Hassan Akhlaq

Reputation: 445

i was able to solve my removing some of the properties in Material React table.

these are my new properties.

 const table = useMaterialReactTable({
  columns: tableColumns.current,
  data: flatReportData,
  enablePagination: false,
  enableRowVirtualization: true,
  enableEditing: true,
  manualFiltering: true,
  getRowId: (originalRow) => originalRow.id,
  muiTableContainerProps: {
    ref: tableContainerRef,
    sx: { maxHeight: '600px' },
    onScroll: (event) => fetchMoreOnBottomReached(event.target),
  },
  muiToolbarAlertBannerProps: isError
    ? { color: 'error', children: 'Error loading data' }
    : undefined,
  renderBottomToolbarCustomActions: () => (
    <Typography>
      Fetched {totalFetched} of {totalDBRowCount} total rows.
    </Typography>
  ),
  state: {
    expanded,
    // globalFilter,
    isLoading: false,
    showAlertBanner: isError,
    showProgressBars: isFetching,
    sorting,
    showSkeletons: false,
  },
  rowVirtualizerInstanceRef,


  enableExpandAll: false,
  enableColumnFilters: false,
  enableColumnActions: false,
  enableFullScreenToggle: false,
  enableDensityToggle: false,
  positionActionsColumn: 'last',
  initialState: { 
    // columnPinning: { left: ['mrt-row-actions'], right: [] },
    // density: 'compact' 
  },
  enableHiding: false,
  rowVirtualizerOptions: { overscan: 10 },
  // onGlobalFilterChange: setGlobalFilter,
  onExpandedChange: setExpanded,
  enableTopToolbar: false,
  enableExpanding: true,
  getRowCanExpand: (row) => row.original.level < levels.length,
  getSubRows: (row) =>
    data?.pages
      ?.flatMap((page) => page.data)
      .filter((r) => r.parentId === row.id),
  onSortingChange: setSorting,
  renderRowActions: ({ row, staticRowIndex, table }) => (
    row.original.level > 1 ? (
      <Box sx={{ display: 'flex', gap: '1rem' }}>
      <Tooltip title="Get more rows">
        <IconButton >
          <EditIcon />
        </IconButton>
      </Tooltip>
   
      
    </Box>
    ) :(<></>)
    
    ),
  muiTableHeadCellProps: {
    sx: {
      color: `${theme.palette.text.rowHeader}`,
      border: 'none',
      paddingTop: '2rem',
      paddingBottom: '1.5rem',
    },
  },
  muiTablePaperProps: {
    sx: {
      boxShadow: 'none',
    },
  },
  muiTopToolbarProps: {
    sx: {
      backgroundColor: `${theme.palette.background.paper}`,
    },
  },
  muiTableHeadRowProps: {
    sx: {
      backgroundColor: `${theme.palette.background.paper}`,
      color: `${theme.palette.text.rowHeader}`,
    },
  },
  muiTableBodyCellProps: {
    sx: {
      border: 'none',
      color: `${theme.palette.text.tableDetail}`,
      paddingTop: '1.0rem',
      paddingBottom: '1.0rem',
    },
  },
  muiTableBodyProps: {
    sx: {
      '& tr:nth-of-type(odd)': {
        backgroundColor: `${theme.palette.background.tableRow}`,
      },
      '& tr:nth-of-type(even)': {
        backgroundColor: `${theme.palette.background.paper}`,
      },
    },
  },
  muiTablePaginationProps: {
    sx: {
      '& .MuiTablePagination-select': {
        paddingTop: '1.2rem',
      },
    },
  },
  muiBottomToolbarProps: {
    sx: {
      '&.MuiToolbar-root': {
        minHeight: '5rem',
        backgroundColor: `${theme.palette.background.paper}`,
        color: `${theme.palette.text.tableDetail}`,
      },
    },
  },
});

Hope that helps

Upvotes: 0

Related Questions