Skip to main content

Events

Two ways to react to the grid: callbacks (one hook each) and the event bus (one stream for all of them). Both are usable from any repo that imports package:bcell/bcell.dart.

Callbacks

Pass them straight to BCellGrid:

BCellGrid(
columns: cols,
rows: rows,
onLoaded: (e) => _sm = e.stateManager, // grid is ready
onChanged: (e) => print('${e.oldValue} -> ${e.value} at row ${e.rowIdx}'),
onSelected: (e) => print('selected ${e.cell?.value}'),
onSorted: (e) => print('sorted ${e.column.title}, was ${e.oldSort}'),
)

Event fields:

EventFields
BCellGridOnLoadedEventstateManager
BCellGridOnChangedEventcolumnIdx, column, rowIdx, row, value, oldValue
BCellGridOnSelectedEventrow?, rowIdx?, cell? (all null when cleared)
BCellGridOnSortedEventcolumn, oldSort

Event bus (one stream, all events)

The bus is a stdlib StreamController.broadcast() — subscribe once and get every event, switch on the type. Cancel the subscription in dispose.

StreamSubscription<BCellGridEvent>? _sub;

BCellGrid(
columns: cols,
rows: rows,
onLoaded: (e) {
_sub = e.stateManager.eventManager.listener((event) {
switch (event) {
case BCellGridOnLoadedEvent():
// ready
case BCellGridOnChangedEvent(:final value, :final rowIdx):
// a cell changed
case BCellGridOnSelectedEvent(:final cell):
// selection moved (cell is null when cleared)
case BCellGridOnSortedEvent(:final column):
// a column sort changed
default:
// your own custom events land here too (see below)
}
});
},
);


void dispose() {
_sub?.cancel();
super.dispose();
}

Emit your own events ("create event, then use event")

BCellGridEvent is an open interface. Define your own event class and emit it through the manager — every listener receives it. This lets a host app push its domain events onto the same stream the grid uses.

// 1. Create an event type.
class RowFlaggedEvent implements BCellGridEvent {
const RowFlaggedEvent(this.rowIdx);
final int rowIdx;
}

// 2. Emit it (e.g. from a button, a service callback, anywhere with the manager).
stateManager.emit(RowFlaggedEvent(3));

// 3. Use it — the same listener above catches it in `default`, or match the type:
_sub = stateManager.eventManager.listener((event) {
if (event is RowFlaggedEvent) {
// react to your own event
}
});

emit is a no-op until someone has accessed eventManager to subscribe, so grids that never listen pay nothing.