Is there a way to autosize column width to content?
I'm looking for a way to size a column to fit the longest possible content rendered in that cell. So for example, if all rows would render content of 100px for this column, the column would be 100px wide -- but if one row renders 200px of content, the column would be 200px wide.
Is there a way to do that?
Unfortunately we don't provide anything out of the box. You could conceivably implement this yourself and plug in to FDT though. You could approach it 2 ways depending on an accuracy / performance trade-off.
Approach 1: Render all cells to the DOM offscreen outside of FDT. Find the max the width of all cells and pass that value to FDT. This would be the more accurate but slower approach since it requires rendering all cells in a column (and fetching all data).
Approach 2: Wrap your cell component in a HOC which measures the cell width after rendering. This width value could then be passed to some state store / cache which can be used to calculate the max width and use that to size the column. This would be faster since it uses FDT to only render cells in the viewport, but would be inaccurate since scrolling might alter the max width if a wider cell scrolls into view.
This approach would be similar to React Virtualized's CellMeasurer.
I was debating about 2 different approaches where the consumer calculates this:
Approach 1 (calculate ahead of time and keep up to date): Add a maxContentWidth prop to the Cell and when the resizer is double clicked the FDT calls onColumnResizeEnd with that prop value for that column.
Approach 2 (calculate on demand): Add a getColumnSnappedWidth callback attribute to the FDT that we call when the resizer is double clicked with the columnKey, firstRowIndex, endRowIndex and then the consumer can calculate it for that column for all the data or for just the data that is present on the screen. Then FDT calls onColumnResizeEnd with that value it got back.
Thoughts?
@Tanner-MS , thanks for you suggestions. A couple questions:
Approach 1 (calculate ahead of time and keep up to date): Add a maxContentWidth prop to the Cell and when the resizer is double clicked the FDT calls onColumnResizeEnd with that prop value for that column.
Is the maxContentWidth just a prop passed by the user?
If so, since the max width is already available to the user, the user can simply pass in an onDoubleClick prop to the cell renderer.
The user can then make the handler resize the column based on the already computed maxContentWidth.
One advantage of customizing the onDoubleClick handler like this would be that FDT doesn't have to know about max content widths, nor would we fix the implementation of the double click handler.
Approach 2 (calculate on demand): Add a getColumnSnappedWidth callback attribute to the FDT that we call when the resizer is double clicked with the columnKey, firstRowIndex, endRowIndex and then the consumer can calculate it for that column for all the data or for just the data that is present on the screen. Then FDT calls onColumnResizeEnd with that value it got back.
Same reasoning as above. We can have the user pass in a double click handler which uses the consumer to calculate the max content width on the fly.
@pradeepnschrodinger
Is the maxContentWidth just a prop passed by the user? If so, since the max width is already available to the user, the user can simply pass in an onDoubleClick prop to the cell renderer. The user can then make the handler resize the column based on the already computed maxContentWidth.
maxContent width would be different than maxWidth. Max content is the widest width your value content would reach, max width is the largest the cell can go. Assuming this is the largest you can resize to as well. Also for this functionality you only want the double click on the resizer, not anywhere else in the header cell. While the user could parse this out based on the target of the event.
Same reasoning as above. We can have the user pass in a double click handler which uses the consumer to calculate the max content width on the fly.
Guess same reason as having this built in makes it simpler on the consumer. They wouldnt have to query the target of the double click.
maxContent width would be different than maxWidth. Max content is the widest width your value content would reach, max width is the largest the cell can go.
Apologies for the confusion; I meant to use maxContentWidth instead of maxWidth.
Since, maxContentWidth is already precomputed by the user, they can just have the onDoubleClick handler make use of it, without having FDT know about maxContentWidth.
Also for this functionality you only want the double click on the resizer, not anywhere else in the header cell. While the user could parse this out based on the target of the event.
Good points
Guess same reason as having this built in makes it simpler on the consumer. They wouldnt have to query the target of the double click.
Definitely. Passing a generic double click handler that targets just the resizer sounds like a better idea, maybe something like onColumnResizerDoubleClick?
The user can keep track of the current row indices through handlers like onScrollEnd, so all the information to calculate maxContentWidth on the fly will be available to the user.
Also as a side note: In the v2.0-beta branch, we've moved out the resizing functionality from the main table component to a separate plugin based cell component.
Here, props like minWidth and onColumnResizeEnd, belong to the cell component.
So adding another prop like onColumnResizerDoubleClick will be relatively simpler than in master.
Also, since these plugins are decoupled out of the table component, we could even have a new plugin that contains business logic to compute the actual max content width.