Currently you have to manually set the sizes of each column, but we've had requests for the columns to auto-size based on their contents.
It'd be fine if this were a instance method function like the resize rows functions: http://blueprintjs.com/docs/#table-js.instance-methods.
It could either by a getColumnWidths function, or a autoSetColumnWidths(maxSize).
Had another request for this to include the width of the text in the header cell.
@Que3216 what do you mean by include the width of the text in header cell? Today if you double click the column resize handle, it should include the header cell width
Agreed on the larger feature of an instance method to resize columns (as if double clicking on each resize handle). Though I don't know when resources will be available to do it
Ah that's cool, though I think we'd want it to just size automatically.
I mean that if you call autoSetColumnWidths(maxSize) then it'll make the column wide if the header is wide even if all the values are thin -- i.e. it takes into account the headers as well as the values.
@giladgray why won't this be fixed? Is there a suggested workaround (that I can't see in the docs)? Thanks
I'm not sure why this was closed either. I could imagine accepting a PR which adds an instance method called something like resizeColumnsByApproximateWidth to auto-size column widths.
Is there a way to provide percentage control, such as: I have ten columns of data, each column I can give different widths, rather than pure numbers?
@coolliyong no, but I would be open to adding that feature as well, in a separate PR
In case this helps anyone, it's possible to adapt the approach taken in the library to do this within a React component as follows:
private table = createRef<Table>()
constructor(props: Readonly<{}>) {
super(props);
this.state = {
columnWidths: [],
resized: false
}
}
clamp(val: number, min: number, max: number) {
if (val == null) {
return val;
}
return Math.min(Math.max(val, min), max);
}
resizeColumns() {
const minColumnWidth = 100;
const maxColumnWidth = 250;
if (this.table.current) {
let newColumnWidths: number[] = [];
for (let i = 0; i < this.state.columnWidths.length; i++) {
const width = this.table.current.locator.getWidestVisibleCellInColumn(i);
const clampedWidth = this.clamp(width, minColumnWidth, maxColumnWidth);
newColumnWidths.push(clampedWidth);
}
this.setState({
columnWidths: newColumnWidths,
resized: true
});
}
}
render() {
<Table ref={this.table} columnWidths={this.state.columnWidths} onCompleteRender={() => {
if (!this.state.resized) {
this.resizeColumns();
}
}}>
...
</Table>
...
}
I did something similar.
```javascript
columnWidts(ref) {
let containerSize = document.getElementsByClassName("bp3-table-container")[0].clientWidth
let totalMinSizeReq = 0;
let cumulativeColumnWidths= [];
for (let index = 0; index < ref.locator.grid.numCols; index++) {
totalMinSizeReq = totalMinSizeReq + ref.locator.getWidestVisibleCellInColumn(i);
cumulativeColumnWidths.push(ref.locator.getWidestVisibleCellInColumn(i));
}
if (totalMinSizeReq > containerSize) {
return cumulativeColumnWidths;
} else {
let diff = ((containerSize - totalMinSizeReq) / ref.locator.grid.numCols);
return cumulativeColumnWidths.map(columnWidt => columnWidt + diff)
}
}
...
Here's how to do it with hooks.
const getColumnWidth = (table: React.RefObject<Table>) => (index: number) =>
table.current?.locator.getWidestVisibleCellInColumn(index) ?? 0
export const Schedules = () => {
const table = useRef<Table>(null)
const [columnWidths, setColumnWidths] = useState([0, 0, 0])
const resizeColumns = useCallback(() => {
setColumnWidths(mapWithIndex(getColumnWidth(table)))
}, [setColumnWidths, table])
return (
<Table
ref={table}
numRows={schedules.length}
columnWidths={columnWidths}
onCompleteRender={resizeColumns}
>
....
Most helpful comment
Here's how to do it with hooks.