Replies: 9 comments 16 replies
-
I'd also like to be able to set a percentage-based width, which doesn't seem possible |
Beta Was this translation helpful? Give feedback.
-
I've come up with a const table = useReactTable<T>({
defaultColumn: {
minSize: 0,
size: 0,
},
getCoreRowModel: getCoreRowModel(),
...
}) Then, in the definition for each header and cell, I apply the style only if the calculated width != 0: // Header
<th
key={header.id}
colSpan={header.colSpan}
style={{
width: header.getSize() !== 0 ? header.getSize() : undefined,
}}
>
...
// Cell
<td
key={cell.id}
style={{
width:
cell.column.getSize() !== 0
? cell.column.getSize()
: undefined,
}}
>
... This will ensure that a style will only be applied if the column specifically defines it. Remember that this doesn't actually change the result of |
Beta Was this translation helpful? Give feedback.
-
The temporary fix suggested above didn't work for my use case so I came up with the following solution:
const cellRefs = React.useRef<HTMLDivElement[][]>([])
const handleCellRefsSet = React.useCallback(
(el: HTMLDivElement, row: number, cell: number) => {
if (!cellRefs.current[row]) cellRefs.current[row] = new Array(originalColumns.length)
cellRefs.current[row][cell] = el
},
[originalColumns.length]
)
const columns = React.useMemo(() =>
originalColumns.map((col, i) => ({
...col,
// Use `scrollWidth` to get the width of the element including its (maybe) hidden fragment.
size: Math.max(...cellRefs.current.map((refs) => refs[i].scrollWidth), col.minSize!),
}),
[originalColumns]) |
Beta Was this translation helpful? Give feedback.
-
the easiest temorary solution is
|
Beta Was this translation helpful? Give feedback.
-
Like @sikorjan answer, we can also do this to avoid as cast
|
Beta Was this translation helpful? Give feedback.
-
Currently we are migrating to V8, this is the solution which we came up with for auto size and resize, work pretty fine for us. Note: wrap the whole thing with a grid, if you need horizontal scrolls for columns which overflow, also have a maxSize property on defaultColumn e.g. {row.getVisibleCells().map((cell) => (
<Flex
role="cell"
key={cell.id}
minH={9}
alignItems={'center'}
px={4}
flex={`${cell.column.getSize()} 0 auto`}
w={`${cell.column.getSize()}px`}
minW={`${cell.column.columnDef.minSize}px`}
>
<Text
as="span"
fontSize="sm"
color={'white'}
textOverflow={'ellipsis'}
overflow={'hidden'}
whiteSpace={'nowrap'}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</Text>
</Flex>
))}
</Flex>
))} P.S. the above example is only for cell, the same can be done for header |
Beta Was this translation helpful? Give feedback.
-
Being able to use percentages or auto even with resizing would be a sweet addition. The proposed "hacks" here all don't work when you use resizing or when you allow the widths to be 0 by having an overflow-ellipsis. |
Beta Was this translation helpful? Give feedback.
-
I think I found good official example here https://tanstack.com/table/v8/docs/framework/react/examples/full-width-resizable-table |
Beta Was this translation helpful? Give feedback.
-
I implemented a solution where we have an option to set Initial column width in percentage + auto-sizing (flex-grow) + it can be resized without any problems. Here is a Live Codesandbox Example Custom column width calculation function:How to use:1- Add this function in your codebase:
function getSize(size = 100, max = Number.MAX_SAFE_INTEGER, min = 40) {
return Math.max(Math.min(size, max), min);
}
/**
* Calculates the sizing of table columns and distributes available width proportionally.
* This function acts as an extension for TanStack Table, ensuring proper column sizing
* based on provided metadata, including `isGrow`, `widthPercentage`, and size constraints.
*
* @template DataType - The generic type of data used in the table rows.
*
* @param {Header<DataType, unknown>[]} columns - An array of column headers. Each header contains
* metadata about the column, including size, constraints, and growth behavior.
* @param {number} totalWidth - The total width available for the table, including padding and margins.
*
* @returns {Record<string, number>} An object mapping column IDs to their calculated sizes.
*/
export const calculateTableSizing = <DataType>(
columns: Header<DataType, unknown>[],
totalWidth: number
): Record<string, number> => {
let totalAvailableWidth = totalWidth;
let totalIsGrow = 0;
columns.forEach((header) => {
const column = header.column.columnDef;
if (!column.size) {
if (!column.meta?.isGrow) {
let calculatedSize = 100;
if (column?.meta?.widthPercentage) {
calculatedSize = column.meta.widthPercentage * totalWidth * 0.01;
} else {
calculatedSize = totalWidth / columns.length;
}
const size = getSize(calculatedSize, column.maxSize, column.minSize);
column.size = size;
}
}
if (column.meta?.isGrow) totalIsGrow += 1;
else totalAvailableWidth -= getSize(column.size, column.maxSize, column.minSize);
});
const sizing: Record<string, number> = {};
columns.forEach((header) => {
const column = header.column.columnDef;
if (column.meta?.isGrow) {
let calculatedSize = 100;
calculatedSize = Math.floor(totalAvailableWidth / totalIsGrow);
const size = getSize(calculatedSize, column.maxSize, column.minSize);
column.size = size;
}
sizing[`${column.id}`] = Number(column.size);
});
return sizing;
}; 2- Defining our columns:We have 2 custom column properties added {
header: "Name",
accessorKey: "name",
footer: (props) => props.column.id,
cell: (info) => info.getValue(),
meta: {
widthPercentage: 30,
},
},
{
header: "Info",
accessorKey: "info",
footer: (props) => props.column.id,
cell: (info) => info.getValue(),
meta: {
isGrow: true,
},
}, 3- Setting it in
|
Beta Was this translation helpful? Give feedback.
-
I guess it is no longer possible to create auto-sizing columns based on the content of the cell?
So the column would have min width of the widest cell in the column.
I found this discussion but the "auto" value is no longer possible for sizing. We can set only numbers now.
#3192
Beta Was this translation helpful? Give feedback.
All reactions