Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TanStack react table v8 style each cell based on the cell value

We are migrating our tables from v7 to v8. And I'm kinda got a problem with cells conditional styling. So basically what I want to do is, based on a status (which is coming to table data) I need to add a specific className to every cell in a row.

In v7 we used this: https://react-table-v7.tanstack.com/docs/examples/data-driven-classes-and-styles

But in v8 I can't find anything like that....

So far I tried to use meta in column definitions https://tanstack.com/table/v8/docs/api/core/column-def#meta where I can set some values to className property, and use it in my JSX like this:

className={cell.column.columnDef.meta?.className}

But problem is anything I can set to meta are static values. For my case I need to set specific className based on my status value. And seems like in meta we can't access any cell props...

const driverFormatter = ({ row }) => {
  const { status } = row.original;

  return <span>{status}</span>;
};

const columns: ColumnDef<any,any>[] = [
    {
      accessorKey: "customerName",
      header: "Customer"
    },
    {
      accessorKey: "driver",
      header: "Driver",
      enableSorting: false,
      cell: driverFormatter,
      meta: {
          className: "disabled",
     },
    },
    ...

So is there are any way of achieving that using v8???

Thank you!

like image 376
Null Avatar asked May 18 '26 15:05

Null


1 Answers

First Method - Through column definition meta key:

We can get the detailed context of each cell in V8 through meta, like

{
    accessorKey: 'section',
    cell: (info) => info.getValue(),
    footer: (props) => props.column.id,
    meta: {
        getCellContext: (context: CellContext<Person, unknown>) => {
            if (context.row.index === 0) {
                // console.log(context)
                return {
                    style: { fontWeight: 'bold', minWidth: '30%', textTransform: 'uppercase' },
                    className: 'bold',
                }
            }
        },
    },
},

To get dynamic context like this, we need to include additional props to ColumnMeta.

declare module '@tanstack/react-table' {
    interface ColumnMeta<TData, TValue> {
        // Your additional properties here
        getCellContext: (context: CellContext<TData, TValue>) => TableCellProps | void
    }
}

Then we can use this func inside the loop

<TableBody>
    {table
        .getRowModel()
        .rows.slice(0, 20)
        .map((row) => {
            return (
                <TableRow key={row.id} {...getRowProps(row)}>
                    {(isSplit ? row.getCenterVisibleCells() : row.getVisibleCells()).map((cell) => {
                        let hasMeta = cell.getContext().cell.column.columnDef.meta

                        return (
                            <TableCell
                                key={cell.id}
                                {...(hasMeta && { ...hasMeta.getCellContext(cell.getContext()) })}
                            >
                                {flexRender(cell.column.columnDef.cell, cell.getContext())}
                            </TableCell>
                        )
                    })}
                </TableRow>
            )
        })}
</TableBody>

By this, you can add styles, className,, etc. To each *** TABLE CELL*** based on the value.

But you can't style the TABLE ROW with the above method. For that

Second Method - Through callback function:

Define two functions for rows and cells

// Func to provide props to table row
const getRowProps = (context: Row<Person>): TableRowProps | void => {
    console.log(context)
    if (context.original.section.includes('section')) {
        return { className: 'sectionHeader', sx: (theme) => ({ background: theme.palette.primary.light }) }
    }
}

// Func to provide props to table cell
const getCellProps = (context: CellContext<Person, unknown>): TableCellProps | void => {
    if (context.row.index === 0) {
        // console.log(context)
        return {
            style: { fontWeight: 'bold', minWidth: '30%', textTransform: 'uppercase' },
            className: 'bold',
        }
    }
}

And just destructure the functions

<TableBody>
    {table
        .getRowModel()
        .rows.slice(0, 20)
        .map((row) => {
            return (
                <TableRow key={row.id} {...getRowProps(row)}>  //<- here
                    {row.getLeftVisibleCells().map((cell) => {

                        return (
                            <TableCell
                                key={cell.id}
                                {...getCellProps(cell.getContext())} // <-here
                            >
                                {flexRender(cell.column.columnDef.cell, cell.getContext())}
                            </TableCell>
                        )
                    })}
                </TableRow>
            )
        })}
</TableBody>
like image 56
Lokesh K Avatar answered May 21 '26 05:05

Lokesh K



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!