Column Sizing
Columns can be configured to have either a fixed or flexible size. In addition, you can have column min and max sizes and also default column sizes.
Note
Use columnDefaultWidth
to configure the default column width. If a column is not sized otherwise, this will be applied. The default value for columnDefaultWidth
is 200
(pixels).
For setting a minimum and maximum width for all columns, use columnMinWidth
(defaults to 30
) and columnMaxWidth
(defaults to 2000
) respectively.
Sizing the column is done via the controlled columnSizing
prop and it’s uncontrolled variant, defaultColumnSizing
. If you want to get updates to columns changing size as a result of user interaction, use onColumnSizingChange
.
Fixed vs flexible sizing
The columnSizing
prop is an object (or Map) of column ids to column sizing objects. Those sizing objects can have the following properties:
flex
- use this for flexible columns. Behaves like the flex CSS property.width
- use this for fixed sized columnsminWidth
- specifies the minimum width of the column. Useful for flexible columns or for restricting users resizing both fixed and flexible columns.maxWidth
- specifies the maximum width of the column. Useful for flexible columns or for restricting users resizing both fixed and flexible columns.
Note
If a column is not specified in the columnSizing
prop (or its uncontrolled variant), or sized otherwise (eg: via the column type), it will have a fixed size, defaulting to columnDefaultWidth
(which also defaults to 200
if no value is passed in).
const columnSizing: InfiniteTablePropColumnSizing = {
country: {
flex: 1,
// minWidth is optional
minWidth: 200
},
city: {
width: 400,
// and so is maxWidth
maxWidth: 500
},
salary: {
flex: 3
}
}
// any column not specified in the columnSizing (or defaultColumnSizing) prop
// will have fixed width (defaulting to `columnDefaultWidth`, which in turn defaults to 200px)
Note
You might find specifying the column size outside the column object to be a bit verbose to start with, but it will be easier to manage in many cases and is much more flexible. For example, when the user resizes a column via d&d (COMING SOON) and you want to persist the new column sizes, you don’t have to update the whole columns
map but instead update columnSizing
alone.
The same principle is true for columnPinning
and other column-level props.
Deep Dive
Flexible sizing explained
Take a look at the snippet below to see column sizing at work with flexible and fixed columns.
import * as React from 'react'; import { InfiniteTable, DataSource, InfiniteTablePropColumnSizing, InfiniteTableColumn, } from '@infinite-table/infinite-react'; export const columns = new Map< string, InfiniteTableColumn<Employee> >([ [ 'firstName', { field: 'firstName', header: 'First Name', }, ], [ 'country', { field: 'country', header: 'Country', }, ], [ 'city', { field: 'city', header: 'City', }, ], [ 'salary', { field: 'salary', type: 'number', header: 'Salary', }, ], ]); const columnSizing: InfiniteTablePropColumnSizing = { country: { width: 100 }, city: { flex: 1, minWidth: 100 }, salary: { flex: 2, maxWidth: 500 }, }; export default function App() { return ( <DataSource<Employee> data={dataSource} primaryKey="id"> <InfiniteTable<Employee> columns={columns} columnDefaultWidth={50} columnSizing={columnSizing} /> </DataSource> ); } const dataSource = () => { return fetch( 'https://infinite-table.com/.netlify/functions/json-server' + '/employees100' ) .then((r) => r.json()) .then((data: Employee[]) => data); }; export type Employee = { id: number; companyName: string; companySize: string; firstName: string; lastName: string; country: string; countryCode: string; city: string; streetName: string; streetNo: string; department: string; team: string; salary: number; age: number; email: string; };
Note
You might find viewportReservedWidth
useful for advanced configuration when you have flexible columns.
Gotcha
You can also size (generated) group columns by using their column.id
property.
For groupRenderStrategy=“multi-column”
, if no id
is specified in the group column configuration, each column will have a generated id like this: "group-by-${field}"
.
For groupRenderStrategy=“single-column”
, if no id
is specified in the groupColumn
it will default to: "group-by"
.
Auto-sizing columns
For sizing columns to the width of their content, you can use autoSizeColumnsKey
to declaratively auto-size columns:
- when
autoSizeColumnsKey
is astring
ornumber
and the value of the prop is changed, all columns will be auto-sized. - when
autoSizeColumnsKey
is an object, it needs to have akey
property (of typestring
ornumber
), so whenever thekey
changes, the columns will be auto-sized. Specifying an object forautoSizeColumnsKey
gives you more control over which columns are auto-sized and if the size measurements include the header or not.
When an object is used, the following properties are available:
key
- mandatory property, which, when changed, triggers the updateincludeHeader
- optional boolean, - decides whether the header will be included in the auto-sizing calculations. If not specified,true
is assumed.columnsToSkip
- a list of column ids to skip from auto-sizing. If this is used, all columns except those in the list will be auto-sized.columnsToResize
- the list of column ids to include in auto-sizing. If this is used, only columns in the list will be auto-sized.
import * as React from 'react'; import { InfiniteTable, DataSource, } from '@infinite-table/infinite-react'; import type { InfiniteTablePropColumns } from '@infinite-table/infinite-react'; type Developer = { id: number; firstName: string; lastName: string; country: string; city: string; currency: string; preferredLanguage: string; stack: string; canDesign: 'yes' | 'no'; hobby: string; salary: number; age: number; }; const dataSource = () => { return fetch( 'https://infinite-table.com/.netlify/functions/json-server' + '/developers1k' ) .then((r) => r.json()) .then((data: Developer[]) => data); }; const columns: InfiniteTablePropColumns<Developer> = { id: { field: 'id' }, firstName: { field: 'firstName' }, preferredLanguage: { field: 'preferredLanguage' }, stack: { field: 'stack' }, country: { field: 'country' }, age: { field: 'age', type: 'number' }, salary: { field: 'salary', type: 'number' }, currency: { field: 'currency', type: 'number' }, }; export default function GroupByExample() { const [key, setKey] = React.useState(0); const [includeHeader, setIncludeHeader] = React.useState(false); const autoSizeColumnsKey = React.useMemo(() => { return { includeHeader, key, }; }, [key, includeHeader]); return ( <> <div style={{ color: 'var(--infinite-row-color)', background: 'var(--infinite-background)', }}> <label> <input checked={includeHeader} type={'checkbox'} onChange={(e) => { setIncludeHeader(e.target.checked); }} />{' '} Include header </label> <button style={{ margin: 10, padding: 10, borderRadius: 5, border: '2px solid magenta', }} onClick={() => { setKey((key) => key + 1); }}> Click to auto-size </button> </div> <DataSource<Developer> primaryKey="id" data={dataSource}> <InfiniteTable<Developer> autoSizeColumnsKey={autoSizeColumnsKey} columns={columns} columnDefaultWidth={200} /> </DataSource> </> ); }