Columns
DSG is column based, meaning that all cells of a given column are of the same type and have the same widget. This is why it is more like Notion or Airtable, and less like Excel.
The columns array
Columns are simple objects, and the list of columns is a simple array of column objects:
const columns = [{}, {}]
If you are using typescript:
import { Column } from 'react-datasheet-grid'
type Row = {
firstName: string
lastName: string
}
const columns: Column<Row>[] = [{}, {}]
Built-in columns
To get you started, 6 simple columns are built-in:
textColumn
checkboxColumn
intColumn
floatColumn
dateColumn
isoDateColumn
percentColumn
Each built-in column handles rows of a very specific data type. For instance the textColumn
expects all rows to be strings:
import {
DataSheetGrid,
textColumn,
} from 'react-datasheet-grid'
const ExampleStrings = () => {
const [ data, setData ] = useState(['foo', 'bar', 'baz'])
const columns = [textColumn]
return (
<DataSheetGrid
value={data}
onChange={setData}
columns={columns}
/>
)
}
And the checkboxColumn
expects all rows to be booleans:
import {
DataSheetGrid,
checkboxColumn,
} from 'react-datasheet-grid'
const ExampleBooleans = () => {
const [ data, setData ] = useState([true, false, true])
const columns = [checkboxColumn]
return (
<DataSheetGrid
value={data}
onChange={setData}
columns={columns}
/>
)
}
This means that columns are very simple, we will see in the next sections how to integrate them in more complex scenarios.
Overriding column props
Because columns are simple objects, you can easily override any property by spreading it. See the exhaustive list of properties a column has.
const columns = [
{
...textColumn,
title: 'Name',
minWidth: 200
}
]
This is a great way to factor common behaviors across multiple columns without repeating code.
Using objects as rows
In a real world project rows often are objects, and we would like each column to handle
a specific key of that object. This is where keyColumn
comes in:
import {
DataSheetGrid,
checkboxColumn,
textColumn,
keyColumn,
} from 'react-datasheet-grid'
const Example = () => {
const [ data, setData ] = useState([
{ active: true, firstName: 'Elon', lastName: 'Musk' },
{ active: false, firstName: 'Jeff', lastName: 'Bezos' },
])
const columns = [
keyColumn('active', checkboxColumn),
keyColumn('firstName', textColumn),
keyColumn('lastName', textColumn),
]
return (
<DataSheetGrid
value={data}
onChange={setData}
columns={columns}
/>
)
}
keyColumn
wraps all properties of a column and allows you to write simpler columns that don't need to worry about an entire row object.
It also has a very positive performance impact.
Because columns wrapped with keyColumn
are still regular objects, you can override any props by spreading it:
const columns = [
{
...keyColumn('active', checkboxColumn),
title: 'Active'
},
{
...keyColumn('firstName', textColumn),
title: 'First name'
},
{
...keyColumn('lastName', textColumn),
title: 'Last name'
},
]
Typescript
keyColumn
is a generic that takes the row type and the key as parameters:
const columns = [
{
...keyColumn<Row, 'active'>('active', checkboxColumn),
title: 'Active'
},
// ...
]
Unfortunately, due to the complexity of the type, you have to type the key twice: once for the generic type, and once for the parameter (eg. 'active'
is written twice).
Responsive width
Columns are responsive by design. DSG uses the flexbox algorithm to dynamically compute the width of each column.
By default, all columns have the same width and a min-width of 100:
You can use the grow
property to make a specific column grow faster. Here the middle column is twice as large as other columns:
You can pass grow: 0
to prevent a column from growing:
Use minWidth
to prevent columns from shrinking too much. By default columns already have minWidth: 100
:
Read more about each property in the API reference.
Building custom columns
Built-in columns are there to get your project started, but often you end up building you own custom columns to fit your needs. Note that built-in columns and helpers have nothing special, they are built on top of this library and do not ofer any additional feature that would not be available otherwise.
Text-based columns
To create a text-based column that simply has some custom parsing and formatting functions you do not have
to implement a custom component from scratch and can instead use createTextColumn
:
import { createTextColumn } from 'react-datasheet-grid'
const column = createTextColumn({ /* options */ })
// When using Typescript you may specify the data type:
const column = createTextColumn<number>({ /* options */ })
The createTextColumn
function returns a column object that can be used normally:
const columns = [
{
...keyColumn(
'name',
createTextColumn({
placeholder: 'Name of the person',
alignRight: true,
//...
})
),
title: 'Name'
},
]
You can also create a custom re-usable column instead of inline it:
// columns/email.tsx
export const emailColumn = createTextColumn({ /* Custom parser & formatter for emails */ })
// index.tsx
import { emailColumn } from './columns/email'
const columns = [
{
...keyColumn('email', emailColumn),
title: 'Email'
},
]
placeholder
Type:
string
Default:null
alignRight
Type:
boolean
Default:false
continuousUpdates
Type:
boolean
Default:true
When true, data is updated as the user types, otherwise it is only updated on blur.
Setting it to false
will improve performance.
deletedValue
Type:
T
Default:null
Value to use when deleting the cell
parseUserInput
Type:
(value: string) => T
Parse what the user types
formatBlurredInput
Type:
(value: T) => string
Format the value of the input when it is blurred
formatInputOnFocus
Type:
(value: T) => string
Format the value of the input when it gets focused
formatForCopy
Type:
(value: T) => string
Format the value when copy
parsePastedValue
Type:
(value: string) => T
Parse the pasted value
Using a custom component
If you need a more exotic column, you can write your own from scratch. A column consists of a custom component that renders the widget and a few props to control its behavior.
See a step-by-step example of how to implement a select column, or read the exhaustive list of properties a column has.
const columns = [
{
component: MyWidget,
title: 'My column'
}
]