'Antd Resizable table columns in TypeScript
I'm implementing antd
<Table>
component and need to make columns resizable with react-resizable
.
I was following the example in the documentation, but since my project in in TypeScript and using functional components I had to refactor it and I've faced issues with typings.
When I'm trying to implement that onHeaderCell
from example:
const initialColumns: ColumnProps<Row>[] = myData.columns.map((column, index) => {
return {
...
onHeaderCell: (c: ColumnType<Row>) => ({
width: c.width,
onResize: handleResize(index),
}),
...
})
I'm getting this error:
... The types returned by 'onHeaderCell(...)' are incompatible between these types. Type '{ width: string | number | undefined; onResize: (e: SyntheticEvent<Element, Event>, resizeData: ResizeCallbackData) => void; }' has no properties in common with type 'HTMLAttributes'.
My handleResize
looks like this:
const handleResize = (index: number) => (e: React.SyntheticEvent<Element, Event>, resizeData: ResizeCallbackData) => {
const { size } = resizeData
updateColumns((cols) => {
const nextColumns = [...cols]
nextColumns[index] = {
...nextColumns[index],
width: size.width,
}
return nextColumns
})
}
I've moved ResizableTitle
into separate component and <Table />
is implemented this way
const components = {
header: {
cell: ResizableTitle,
},
}
return (
<Table
bordered
components={components}
columns={columns} // columns come from the useState<ColumnProps<Row>[]>()
...
/>
)
How can I change this to get desired results?
Solution 1:[1]
So I found a solution without using react-resizable
const [resizingColumnIndex, _setResizingColumnIndex] = useState<number>();
const resizingColumnIndexRef = useRef(resizingColumnIndex);
const setResizingColumnIndex = (index: number | undefined) => {
resizingColumnIndexRef.current = index;
_setResizingColumnIndex(index);
};
const resizeListener = (e: MouseEvent) => {
if (resizingColumnIndexRef.current) {
handleResize(resizingColumnIndexRef.current, e.movementX);
}
window.onmouseup = (e: MouseEvent) => {
window.removeEventListener("mousemove", resizeListener);
setResizingColumnIndex(undefined);
};
};
In each column title I'm adding
<div
className="resizeHandle"
onMouseDown={() => {
setResizingColumnIndex(index);
window.addEventListener("mousemove", resizeListener, { passive: true });
}}
/>
having style of
.resizeHandle {
position: absolute;
width: 10px;
height: 100%;
bottom: 0;
right: -5px;
cursor: col-resize;
z-index: 5;
}
Finally the handleResize
function that updates columns kept in state of the component
const handleResize = (index: number, delta: number) => {
updateColumns(prevColumns => {
const indexNewWidth = Number(prevColumns[index].width) + delta;
const nextWidth = indexNewWidth >= MIN_COLUMN_WIDTH ? indexNewWidth : MIN_COLUMN_WIDTH;
return prevColumns.map((col, i) => (i === index ? { ...col, width: nextWidth } : col));
});
setTableWidth(prevWidth => prevWidth + delta);
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Sergei Klinov |