Change Tracking
FdcDataSet tracks inserted, modified, and deleted records. This allows application code and adapters to work with changes rather than resending an entire dataset.
Record change states
A record can be:
| State | Meaning |
|---|---|
unchanged | No pending local change |
inserted | Newly inserted and not yet accepted |
modified | One or more values differ from accepted values |
deleted | Marked for deletion |
Normal application code rarely needs to manage these states directly. They are maintained by dataset edit operations.
Check for pending changes
if (dataSet.hasUpdates) {
// Persistent inserts, updates, or deletes are pending.
}
hasUpdates reflects persistent changes. An edit limited to non-persistent or calculated fields does not make the dataset report persistent updates.
Inspect the change set
changeSet returns a fresh immutable snapshot:
final changes = dataSet.changeSet;
print(changes.inserts.length);
print(changes.updates.length);
print(changes.deletes.length);
Each entry includes:
- the dataset
recordIdused for result correlation; - current
values; originalValues;changedFields.
For most applications, adapters and dataset APIs consume this model internally. Reading it directly is useful for review screens, diagnostics, audit previews, or custom workflow UI.
The three groups have different persistence meaning:
insertscontain new row values that do not yet exist in accepted storage state,updatescontain current values plus original accepted values and changed-field identity,deletesretain enough original identity/value state for the adapter to delete the accepted storage row.
Key snapshots are especially important when an editable key field changes: storage targeting must use the original accepted key, while the current value can represent the new key state.
Persistent fields determine whether a change belongs in the persistence change set. Non-persistent/calculated fields can participate in UI state without creating storage updates by themselves.
Immediate updates are the default
The default update mode is:
FdcUpdateMode.immediate
With an adapter-backed dataset, post() and delete() commit the local operation and schedule persistence through the adapter.
Use dataset error and work callbacks to observe asynchronous persistence outcomes.
Cached updates
Choose cached updates when the user should make several changes and explicitly save or discard them as a group:
final dataSet = FdcDataSet(
fields: fields,
adapter: adapter,
updateMode: FdcUpdateMode.cachedUpdates,
);
Edit normally:
dataSet.edit();
dataSet['company'] = 'Northstar Systems';
dataSet.post();
dataSet.append();
dataSet['company'] = 'BluePeak Logistics';
dataSet.post();
Then apply all persistent changes:
final result = await dataSet.applyUpdates();
Cancel cached updates
dataSet.cancelUpdates();
cancelUpdates() reverts unapplied cached inserts, edits, and deletes and rebuilds the active view from accepted record state.
This operation is different from cancel():
cancel()discards the current active edit or insert buffer;cancelUpdates()reverts all unapplied cached changes.
After apply succeeds or fails
On successful apply, the dataset accepts the persisted change set and reconciles any backend-confirmed values before returning to a clean accepted state. Generated keys and normalized server values therefore become part of the dataset's accepted row state.
On failed apply, pending tracked changes are not silently accepted. Structured adapter errors flow into the dataset error pipeline so the application can correct values or retry according to its workflow.
For cached updates, this distinction is critical: applyUpdates() is the persistence boundary, while prior post() calls only moved values from the active edit buffer into tracked pending changes.
Backend-confirmed values
When adapter apply succeeds, the dataset can merge backend-confirmed values into affected records. This matters for generated keys, server timestamps, normalized values, and other persistence-side results.
The adapter contract and apply result model are covered in the adapter documentation.
Persistence boundaries
A useful mental model is:
edit buffer
↓ post()
dataset tracked change
↓ applyUpdates() or immediate apply
adapter/storage
This separation allows the same editing UI model to support local data, immediate persistence, and explicit batch-save workflows.
Next: Data Binding