Grid Events and Callbacks
Keep dataset lifecycle behavior in FdcDataSet and visual interaction behavior in FdcGrid.
Cell pointer events
Use onCellTapDown for low-level pointer-down handling and onCellDoubleTap for semantic double-click or double-tap actions:
FdcGrid(
dataSet: customers,
onCellTapDown: (context) {
final position = context.globalPosition;
final column = context.column;
},
onCellDoubleTap: (context) {
openCustomerDetails(context.recordId);
},
)
Both callbacks receive FdcGridCellPointerContext, which exposes:
| Property | Purpose |
|---|---|
dataSet | Dataset attached to the grid. |
row | Stable row context for the target row. |
column | Resolved column configuration. |
rowIndex | Zero-based row index in the current view. |
columnIndex | Zero-based column index in the current layout. |
recordId | Internal dataset record identifier, when available. |
value | Current cell value. |
globalPosition | Pointer position in global coordinates. |
localPosition | Pointer position relative to the target body cell. |
These are notification callbacks. They do not return a decision to the pointer gesture pipeline.
Cell changes
FdcGrid(
dataSet: customers,
onCellChanged: (context) {
final field = context.fieldName;
final oldValue = context.oldValue;
final value = context.value;
},
)
onCellChanged reports an accepted local write. Backend persistence remains part of the dataset apply flow.
Focus transitions
The grid exposes row, column, and exact-cell enter/exit callbacks:
FdcGrid(
dataSet: customers,
onRowEnter: (context) {},
onRowExit: (context) {},
onColumnEnter: (context) {},
onColumnExit: (context) {},
onCellEnter: (context) {},
onCellExit: (context) {},
)
These are notifications, not navigation veto hooks. Validation and posting rules belong in dataset lifecycle events.
Edit permission gates
FdcGrid(
dataSet: customers,
canEditRow: (rowIndex, row) => !row.valueOf<bool>('locked'),
canEditColumn: (rowIndex, column, row) =>
column.fieldName != 'id',
)
Keep these predicates fast and side-effect free because edit traversal can evaluate them repeatedly.
Column value lifecycle
Use onValueChanging to transform or reject the pending value and onValueChanged to observe a successful write for that column.
FdcTextColumn<String>(
fieldName: 'state',
onValueChanging: (context) {
final value = context.newValue?.trim().toUpperCase();
if (value == null || value.length != 2) {
return context.cancel('Use a two-letter state code.');
}
return context.replaceValue(value);
},
onValueChanged: (context) {
debugPrint('State changed to ${context.value}');
},
)
Use the grid-level onCellChanged callback when one screen needs a central notification surface across multiple columns.