Skip to main content

Getting started

Columns

A column binds a title (header), a field (the key into each row's cell map), and a type.

BCellColumn(
title: 'Price',
field: 'price',
type: BCellColumnType.number(format: r'$#,##0.00'), // Excel-style, display-only
width: 120,
readOnly: false, // lock this column
hide: false, // hidden until shown
frozen: BCellColumnFrozen.start, // pin left (or .end / .none)
validator: (v) => '$v'.trim().isEmpty ? 'Required' : null, // reject a bad edit
)

Types:

BCellColumnType.text()
BCellColumnType.number(format: '#,##0') // grouped; '0.0%', r'$#,##0.00'
BCellColumnType.date(format: (d) => '${d.year}-${d.month}') // double-tap = date picker

Rows

A row is a map keyed by each column's field. Values are wrapped in BCellValue so the grid can fire events on change.

BCellRow(
height: 72, // optional per-row height; null = grid default
cells: {
'price': BCellValue(value: 19.99),
'name': BCellValue(value: 'Widget'),
},
)

The whole grid

class MyScreen extends StatefulWidget {
const MyScreen({super.key});

State<MyScreen> createState() => _MyScreenState();
}

class _MyScreenState extends State<MyScreen> {
BCellGridStateManager? _sm;


Widget build(BuildContext context) {
return BCellGrid(
columns: [
BCellColumn(title: 'Id', field: 'id', type: BCellColumnType.number(), width: 80),
BCellColumn(title: 'Name', field: 'name', type: BCellColumnType.text()),
BCellColumn(title: 'Role', field: 'role', type: BCellColumnType.text()),
],
rows: [
for (var i = 0; i < 20; i++)
BCellRow(cells: {
'id': BCellValue(value: i + 1),
'name': BCellValue(value: 'Person $i'),
'role': BCellValue(value: 'Engineer'),
}),
],
mode: BCellGridMode.normal, // or BCellGridMode.readOnly to lock the whole grid
onLoaded: (e) => setState(() => _sm = e.stateManager),
);
}
}

The state manager

The stateManager from onLoaded is the control surface. Common calls:

_sm.changeCellValue(cell, newValue); // edit through the manager (fires events)
_sm.setCurrentCell(cell); // move selection
_sm.appendRows([row]); _sm.removeRows([row]);
_sm.toggleSortColumn(column); // sort a column (cycles asc/desc/none)
_sm.setFilter((row) => ...); // keep matching rows; null clears
_sm.setPageSize(15); _sm.setPage(2); // paginate (source rows untouched)
_sm.toCsv(); // export visible columns + filtered rows

New rows must enter through the manager (appendRows) so their cells get wired with row/column back-references — do not mutate the rows list directly.

Next: Theming · Events · Guides