implement full width resize handler
Describe the bug
The header.getResizeHandler() works well if the table is not full-width. But when working with full-width tables, it does not handle the ColumnSizingState properly.
Your minimal, reproducible example
none
Steps to reproduce
My idea is that we need full-width Resize Handler apart from normal Resize Handler when the table is full-width.
The normal Resize Handler updates the current column size in the ColumnSizingState, but full-width Resize Handler will update the size of both the current column and the next resizable column in the ColumnSizingState.
The logic is simple -->
- if there is ANY resizable column after the current column (not need be adjacent, meaning one of the next columns), update the current column size like normal resize handler, and also, update the size of the FIRST resizable column as many as amount of the width change in negative to keep the table width the same.
- if there is NO resizable column after the current column, do not update the current column size.
- while updating the
ColumnSizingState, respect the min width of the current column and the the FIRST resizable column in order to keep the column sizes in stable.
Expected behavior
I am volunteer to implement the full-width resize handler.
I want to get the package authors' idea and also others' about the way of implementation.
(assume we have a state variable for full width called isFullWidth)
Option-1
to create a separate resize handler --> header.getFullWidthResizeHandler()
the usage could be in the table:
<div
{...{
onMouseDown: isFullWidth ? header.getFullWidthResizeHandler() : header.getResizeHandler(),
onTouchStart: isFullWidth ? header.getFullWidthResizeHandler() : header.getResizeHandler(),
}}
/>
Option-2
to update the current getResizeHandler() having a parameter for full-width --> header.getResizeHandler(isFullWidth)
the usage could be in the table:
<div
{...{
onMouseDown: header.getResizeHandler(isFullWidth),
onTouchStart: header.getResizeHandler(isFullWidth),
}}
/>
After getting your opinions, I am going to proceed for the implementation and will make a PR.
How often does this bug happen?
None
Screenshots or Videos
No response
Platform
macos
react-table version
8.8.6
TypeScript version
4.9.4
Additional context
No response
Terms & Code of Conduct
- [X] I agree to follow this project's Code of Conduct
- [X] I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
I see a clear need for this, the current resize handler does not work for full-width tables, the columnSizing table state and actual column sizes quickly get out of sync such that if you save the state to local storage and try to use that as initial state you get significantly different results. The reason is the same as the one @talatkuyuk is referring to, namely that the onColumnSizingChange updater only passes the updated width of the column you are currently resizing, even though many times other columns are also changing widths to be able to take up the entire width.
If someone has a decent workaround please share.
In my case. If I'm using a full width table. I usually set the last column's width to undefined so the other column sizes will be honored. I think the problem occurs if the sum of all the column width doesn't match with the actual table width. Therefore distributing the remaining width to all the columns.
Scenario:
- Table's actual width is 1000px
- Table has 3 columns and each column has 150px as default.
- The sum of all the columns is 450px as compared to 1000px.
- The remaining 550px will be distributed evenly to the 3 columns.
- Making each column have 333.33px in actual width but 150px in CSS width.
To prevent this. I set the last column to undefined therefore consuming all the excess width.
Here's what it looks like.
<Thead>
{table.getHeaderGroups().map((headerGroup) => (
<Tr key={headerGroup.id}>
{headerGroup.headers.map((header, idx) => (
<Th
colSpan={header.colSpan}
key={header.id}
minW={0}
p={0}
style={{
width:
headerGroup.headers.length - 1 !== idx
? header.getSize()
: undefined,
}}
>
I just briefly looked over this code, not sure the full context on how this works: https://github.com/TanStack/table/blob/main/packages/table-core/src/features/ColumnSizing.ts#L235C26-L235C26
Could the logic here be changed to accommodate both full width and the later?
Having issue with full width, and was looking through the code to see where this might be happening
I just briefly looked over this code, not sure the full context on how this works: https://github.com/TanStack/table/blob/main/packages/table-core/src/features/ColumnSizing.ts#L235C26-L235C26
Could the logic here be changed to accommodate both full width and the later?
Having issue with full width, and was looking through the code to see where this might be happening
come to think of it.. is this not the way it's supposed to work? with the table set in full width mode, the columns appear to be set to widths relative to the table size in full width. if I take those ColumnSizingStates from changing column sizes in UI and set them on init, the table visually looks the same in column widths when I refresh. This appears to be working correctly then?
Here is my use case for a full-width table including a work-around.
I need to show a file list and the name column is supposed to fill the available space.
I achieved this by setting the width for all table headers, except for the name column.
On the right side of the name column there are two resizable columns size and date. Both are aligned to the right.
Because of that I show the resize handles on the left side of the column header.
But when moving the handle to the left, the column size is decreased by the resize handler. So I flip this around before setting the column width:
Column definition:
const columns = [
{
id: 'icon',
size: 38,
enableResizing: false,
},
{
id: 'name',
enableResizing: false,
},
{
id: 'size',
size: 120,
enableResizing: true,
},
{
id: 'date',
size: 200,
enableResizing: true,
},
{
id: 'actions',
size: 32,
enableResizing: false,
},
];
Calculate column width:
const columnSize = (header: Header<unknown, unknown>) => {
switch (header.id) {
case 'name': {
return undefined;
}
case 'size': {
return 120 * 2 - header.column.getSize();
}
case 'date': {
return 200 * 2 - header.column.getSize();
}
default: {
return header.column.getSize();
}
}
};
Render the table:
{table.getFlatHeaders().map((header) => (
<div key={header.id} style={{ width: columnSize(header) }} >
))}
The result:
this worked for me:
const getTableSize = () => {
return Math.max(table.getCenterTotalSize(), tableContainerRef.current?.clientWidth ?? 0);
};
return (
<TableContainer ref={tableContainerRef} style={props.containerStyles}>
<table style={{ width: getTableSize(), tableLayout: 'fixed' }}>
...
ColumnSizingState now returns correctly for me