FdcDataSet constructor
FdcDataSet({
- List<
FdcFieldDef> fields = const <FdcFieldDef>[], - IFdcDataAdapter? adapter,
- FdcUpdateMode updateMode = FdcUpdateMode.immediate,
- FdcRecordValidator? recordValidator,
- FdcDataSetBeforeOpen? beforeOpen,
- FdcDataSetAfterOpen? afterOpen,
- FdcDataSetBeforeClose? beforeClose,
- FdcDataSetAfterClose? afterClose,
- FdcDataSetBeforeEdit? beforeEdit,
- FdcDataSetAfterEdit? afterEdit,
- FdcDataSetBeforeInsert? beforeInsert,
- FdcDataSetAfterInsert? afterInsert,
- FdcDataSetBeforePost? beforePost,
- FdcDataSetAfterPost? afterPost,
- FdcDataSetBeforeDelete? beforeDelete,
- FdcDataSetAfterDelete? afterDelete,
- FdcDataSetBeforeCancel? beforeCancel,
- FdcDataSetAfterCancel? afterCancel,
- FdcDataSetStateChanged? onStateChanged,
- FdcDataSetValidationError? onValidationError,
- FdcDataSetErrorEvent? onError,
- FdcDataSetWorkStarted? onWorkStarted,
- FdcDataSetWorkCompleted? onWorkCompleted,
- FdcDataSetWorkError? onWorkError,
- FdcDataSetFieldChanged? onFieldChanged,
- FdcDataSetNewRecord? onNewRecord,
- FdcDataSetBeforeScroll? beforeScroll,
- FdcDataSetAfterScroll? afterScroll,
- FdcDataSetOperationOptions operationOptions = const FdcDataSetOperationOptions(),
- FdcDataPagingOptions paging = const FdcDataPagingOptions.disabled(),
- FdcFormatSettings? formatSettings,
- FdcValidationTranslations validationTranslations = const FdcValidationTranslations(),
Creates a dataset.
updateMode defaults to FdcUpdateMode.immediate. Pass
FdcUpdateMode.cachedUpdates only when the dataset should buffer changes
until an explicit applyUpdates call.
Implementation
// ignore: sort_constructors_first
FdcDataSet({
List<FdcFieldDef> fields = const <FdcFieldDef>[],
IFdcDataAdapter? adapter,
FdcUpdateMode updateMode = FdcUpdateMode.immediate,
FdcRecordValidator? recordValidator,
FdcDataSetBeforeOpen? beforeOpen,
FdcDataSetAfterOpen? afterOpen,
FdcDataSetBeforeClose? beforeClose,
FdcDataSetAfterClose? afterClose,
FdcDataSetBeforeEdit? beforeEdit,
FdcDataSetAfterEdit? afterEdit,
FdcDataSetBeforeInsert? beforeInsert,
FdcDataSetAfterInsert? afterInsert,
FdcDataSetBeforePost? beforePost,
FdcDataSetAfterPost? afterPost,
FdcDataSetBeforeDelete? beforeDelete,
FdcDataSetAfterDelete? afterDelete,
FdcDataSetBeforeCancel? beforeCancel,
FdcDataSetAfterCancel? afterCancel,
FdcDataSetStateChanged? onStateChanged,
FdcDataSetValidationError? onValidationError,
FdcDataSetErrorEvent? onError,
FdcDataSetWorkStarted? onWorkStarted,
FdcDataSetWorkCompleted? onWorkCompleted,
FdcDataSetWorkError? onWorkError,
FdcDataSetFieldChanged? onFieldChanged,
FdcDataSetNewRecord? onNewRecord,
FdcDataSetBeforeScroll? beforeScroll,
FdcDataSetAfterScroll? afterScroll,
FdcDataSetOperationOptions operationOptions =
const FdcDataSetOperationOptions(),
FdcDataPagingOptions paging = const FdcDataPagingOptions.disabled(),
FdcFormatSettings? formatSettings,
FdcValidationTranslations validationTranslations =
const FdcValidationTranslations(),
}) : _adapter = adapter,
_paging = paging,
_updateMode = updateMode,
_recordValidator = recordValidator,
_beforeOpen = beforeOpen,
_afterOpen = afterOpen,
_beforeClose = beforeClose,
_afterClose = afterClose,
_beforeEdit = beforeEdit,
_afterEdit = afterEdit,
_beforeInsert = beforeInsert,
_afterInsert = afterInsert,
_beforePost = beforePost,
_afterPost = afterPost,
_beforeDelete = beforeDelete,
_afterDelete = afterDelete,
_beforeCancel = beforeCancel,
_afterCancel = afterCancel,
_onStateChanged = onStateChanged,
_onValidationError = onValidationError,
_onError = onError,
_onWorkStarted = onWorkStarted,
_onWorkCompleted = onWorkCompleted,
_onWorkError = onWorkError,
_onFieldChanged = onFieldChanged,
_onNewRecord = onNewRecord,
_beforeScroll = beforeScroll,
_afterScroll = afterScroll {
paging.validate();
_view.operationOptions = operationOptions;
if (formatSettings != null) {
_view.filterContext = _view.filterContext.copyWith(
formatSettings: formatSettings,
);
}
_schemaCoordinator = FdcDataSetSchemaCoordinator(
recordValidator: _recordValidator,
ownerDescription: runtimeType.toString(),
validationTranslations: validationTranslations,
invalidateComparableCacheForField: _invalidateComparableCacheForField,
);
_schemaCoordinator.configure(fields);
_lifecycleCoordinator = FdcDataSetLifecycleCoordinator(
openCore: _openCore,
openFutureCore: _openFutureCore,
loadRowsCore: _loadRowsCore,
loadRowsFutureCore: _loadRowsFutureCore,
closeCore: _closeCore,
);
_workCoordinator = FdcDataSetWorkCoordinator(
captureLifecycleGeneration: _lifecycleCoordinator.captureGeneration,
isLifecycleCurrent: _isLifecycleCurrent,
onStarted: (work) => _onWorkStarted?.call(this, work),
onCompleted: (work) => _onWorkCompleted?.call(this, work),
onError: (work, error, stackTrace) =>
_onWorkError?.call(this, work, error, stackTrace),
);
_errorController = FdcDataSetErrorController(
store: _errorStore,
emitValidationError: (errors) {
_onValidationError?.call(this, errors);
},
emitError: (errors, {Object? cause}) {
_onError?.call(this, errors, cause);
for (final listener in List<FdcDataSetErrorEvent>.of(
_internalErrorListeners,
)) {
listener(this, errors, cause);
}
},
notifyListeners: notifyListeners,
);
_aggregateCoordinator = FdcDataSetAggregateCoordinator();
_cursorCoordinator = FdcDataSetCursorCoordinator(
ensureOpen: _ensureOpen,
readRecordCount: () => recordCount,
readViewIndexes: () => _view.viewIndexes,
resolveActiveEdit: _tryResolveEditForRecordsetChange,
readCurrentRecordId: () => _currentRecordRaw?.id,
runOperation: ({required operation, required recordId, required body}) =>
_errorController.runOperation<void>(
operation: operation,
recordId: recordId,
body: body,
),
beforeScroll: (previousRecordNumber, targetRecordNumber) {
for (final guard in List<void Function()>.of(
_internalBeforeScrollGuards.values,
)) {
guard();
}
_beforeScroll?.call(this, previousRecordNumber, targetRecordNumber);
},
afterScroll: (previousRecordNumber, currentRecordNumber) =>
_afterScroll?.call(this, previousRecordNumber, currentRecordNumber),
notifyListeners: notifyListeners,
);
_recordViewCoordinator = FdcDataSetRecordViewCoordinator(
recordStore: _recordStore,
view: _view,
cursor: _cursorCoordinator,
readRecordMapper: () => _schemaCoordinator.recordMapper,
rebuildView: ({preserveRecordId, required notify}) =>
_rebuildView(preserveRecordId: preserveRecordId, notify: notify),
beforeAppendRows: () {
_bumpDataRevision(adapterQueryChanged: false);
_view.clearComparableValueCache();
},
beforeReplaceRows: (adapterQueryChanged) {
_applyCoordinator.clearPendingImmediateDeletes();
_bumpDataRevision(adapterQueryChanged: adapterQueryChanged);
_view.clearComparableValueCache();
_clearRetainedVisibleRecords();
},
beforeDiscardRecord: (record) {
if (record.selected) {
_selectionCoordinator.syncSelectionKeyForRecord(record, false);
}
_bumpDataRevision(adapterQueryChanged: !_paging.enabled);
_view.clearComparableValueCache();
},
clearEditBuffer: ({required invalidateAggregateCache}) =>
_clearEditBuffer(invalidateAggregateCache: invalidateAggregateCache),
readDiscardInvalidatesAggregateCache: () => !_paging.enabled,
readPagingEnabled: () => _paging.enabled,
);
_applyCoordinator = FdcDataSetApplyCoordinator(
updateMode: _updateMode,
hasUpdates: () => hasUpdates,
readState: () => _state,
ensureOpen: _ensureOpen,
tryPostActiveEdit: _tryPostActiveEdit,
buildApplyChangeSet: _buildApplyChangeSet,
applyLocalChanges: _applyLocalChanges,
beginAdapterApply: _beginAdapterApply,
captureLifecycleGeneration: _lifecycleCoordinator.captureGeneration,
isLifecycleCurrent: _isLifecycleCurrent,
applyAdapterChanges: _applyAdapterChanges,
completeApplyResult: _completeApplyResult,
completeApplyException: _completeApplyException,
readAdapter: () => _adapter,
exceptionMessage: _errorController.exceptionMessage,
);
_editCoordinator = FdcDataSetEditCoordinator(
readState: () => _state,
isImmediateApplyRunning: () => _applyCoordinator.isImmediateApplyRunning,
readPendingImmediatePostRecordId: () =>
_applyCoordinator.pendingImmediatePostRecordId,
hasDirtyEdit: () => _hasDirtyEdit,
ensureWritable: _ensureWritable,
ensureOpen: _ensureOpen,
readCurrentRecord: () => _currentRecordRaw,
clearErrors: () => _errorController.clearErrors(notify: false),
beforeEdit: () => _beforeEdit?.call(this),
beginEdit: (record) => _beginEditBuffer(record, insertRecord: false),
setState: _setState,
afterEdit: () => _afterEdit?.call(this),
notifyListeners: notifyListeners,
runOperation: ({required operation, required recordId, required body}) =>
_errorController.runOperation<void>(
operation: operation,
recordId: recordId,
body: body,
),
ensureBrowseLikeState: _ensureBrowseLikeState,
readCurrentRecordId: () => _currentRecordRaw?.id,
createInsertedRecord: () => _schemaCoordinator.recordMapper
.createInsertedRecord(recordId: _recordStore.takeNextRecordId()),
prepareInsert: (_) {
_bumpDataRevision(adapterQueryChanged: false);
_view.clearComparableValueCache();
},
resolveInsertRawIndex: (target) => target.resolveRawIndex(
currentIndex: _cursorCoordinator.currentIndex,
recordCount: _recordStore.length,
rawIndexForActiveIndex: _recordViewCoordinator.rawIndexForActiveIndex,
),
insertRawRecord: _recordStore.insertRaw,
activateInsertedRecord: _activateInsertedRecord,
emitNewRecordDefaults: _emitNewRecordWithDefaults,
refreshInsertedRecordView: _refreshInsertedRecordView,
rollbackFailedInsert: _rollbackFailedInsert,
beforeInsert: () => _beforeInsert?.call(this),
afterInsert: () => _afterInsert?.call(this),
ensureDeleteAllowed: () {
_ensureWritable();
_ensureOpen();
if (_state == FdcDataSetState.loading ||
_state == FdcDataSetState.applyingUpdates) {
throw StateError('Cannot delete while dataset is busy.');
}
},
beforeDelete: () => _beforeDelete?.call(this),
afterDelete: () => _afterDelete?.call(this),
markPendingImmediateDelete: _applyCoordinator.markPendingImmediateDelete,
markRecordDeleted: (record, oldIndex) {
_bumpDataRevision(adapterQueryChanged: !_paging.enabled);
_view.clearComparableValueCache();
if (record.selected) {
_selectionCoordinator.syncSelectionKeyForRecord(record, false);
}
record.selected = false;
record.state = FdcRecordState.deleted;
_clearEditBuffer(invalidateAggregateCache: !_paging.enabled);
_rebuildViewSelectingNearestRow(oldIndex);
},
ensureEditState: _ensureEditState,
runPostOperation:
({required operation, required recordId, required body}) =>
_errorController.runOperation<void>(
operation: operation,
recordId: recordId,
wrapUnexpected: false,
preserveValidationException: true,
body: body,
),
beforePost: () => _beforePost?.call(this),
calculateCalculatedValues: _applyCalculatedFields,
validatePost: (record, values) => <FdcValidationError>[
..._schemaCoordinator.validator.validateRecord(record, values: values),
..._adapterStorageValidationErrors(record, values),
],
publishValidationErrors: (errors) =>
_errorController.setValidationErrors(errors, notify: true),
changedIndexesBetween: (record, values) => _schemaCoordinator.fieldWriter
.changedIndexesBetween(record.valuesSnapshot(), values)
.toList(growable: false),
applyPostedValues: (record, values, changedIndexes) {
for (final index in changedIndexes) {
record.setValueAt(index, values[index]);
_invalidateComparableCacheForField(index);
}
_bumpDataRevision(invalidateAggregateCache: false);
},
resolvePostedRecordState: (record) {
if (record.state == FdcRecordState.inserted) {
return;
}
record.state = record.changedFieldIndexes().isEmpty
? FdcRecordState.unchanged
: FdcRecordState.modified;
},
retainVisibleRecord: _retainVisibleRecord,
hasAdapter: () => _adapter != null,
readUpdateMode: () => _updateMode,
acceptChanges: (record) => record.acceptChanges(),
clearEditBuffer: ({required invalidateAggregateCache}) =>
_clearEditBuffer(invalidateAggregateCache: invalidateAggregateCache),
markPendingImmediatePost: _applyCoordinator.markPendingImmediatePost,
afterPost: () => _afterPost?.call(this),
scheduleImmediateApply: _scheduleImmediateApplyUpdates,
readPagingEnabled: () => _paging.enabled,
readCurrentIndex: () => _cursorCoordinator.currentIndex,
discardRecordFromStore: _discardRecordFromStore,
rebuildView: ({preserveRecordId}) =>
_rebuildView(preserveRecordId: preserveRecordId, notify: false),
beforeCancel: () => _beforeCancel?.call(this),
afterCancel: () => _afterCancel?.call(this),
);
_pagingCoordinator = FdcDataSetPagingCoordinator(
options: _paging,
openPageCore: _openPage,
);
this.paging = FdcDataSetPagingApi._(this);
selection = FdcDataSetSelectionApi._(this);
aggregates = FdcDataSetAggregatesApi._(this);
bookmarks = FdcDataSetBookmarksApi._(this);
errors = FdcDataSetErrorsApi._(this);
_queryCoordinator = FdcDataSetQueryCoordinator(
pagingEnabled: () => _paging.enabled,
validateSearchFields: _validateSearchFields,
readSearchState: () => _view.searchState,
writeSearchState: (state) => _view.searchState = state,
validateFilterFields: _validateFilterFields,
readFilters: () => _view.filters,
writeFilters: (filters) {
_view.filters
..clear()
..addAll(filters);
},
readFilterContext: () => _view.filterContext,
writeFilterContext: (context) => _view.filterContext = context,
retainedVisibleRecordsAreEmpty: () =>
_view.retainedVisibleRecordIds.isEmpty,
notifyFilterChanged: _notifyFilterChanged,
readSorts: () => _view.sorts,
writeSorts: (sorts) {
_view.sorts
..clear()
..addAll(sorts);
},
normalizeSorts: _normalizeSorts,
isCursorAtFirst: () => _cursorCoordinator.isAtFirst,
resolveActiveEdit: _tryResolveEditForRecordsetChange,
clearRetainedVisibleRecords: _clearRetainedVisibleRecords,
invalidateAggregateCache: _invalidateAggregateCache,
rebuildView: ({required notify, required resetToFirst}) =>
_rebuildView(notify: notify, resetToFirst: resetToFirst),
rebuildViewAsync: ({required notify, required resetToFirst}) =>
_rebuildViewAsync(notify: notify, resetToFirst: resetToFirst),
openFirstPage: () => _pagingCoordinator.openPage(),
notifyListeners: notifyListeners,
);
_selectionCoordinator = FdcDataSetSelectionCoordinator(
pagingEnabled: () => _paging.enabled,
readViewIndexes: () => _view.viewIndexes,
recordAtRawIndex: _recordStore.atRawIndex,
readRecords: () => _recordStore.records,
replaceRecords: (records) => _recordStore.replaceAll(records),
ensureNextRecordIdAfter: (internalIds) =>
_recordStore.ensureNextRecordIdAfter(internalIds),
readFields: () => _fields,
fieldIndexByNormalizedName: (name) =>
_schemaCoordinator.fieldIndexByName[name],
readSelectedFilter: () => _view.filterContext.selected,
setTotalRecordCount: _pagingCoordinator.setTotalRecordCount,
recordToMap: (record, {required includeNonPersistent}) =>
_schemaCoordinator.recordMapper.recordToMap(
record,
includeNonPersistent: includeNonPersistent,
),
);
filter = FdcDataSetFilters(
canApplyViewOperation: () => _canApplyViewOperation,
useAsyncViewOperations: () => _paging.enabled,
readFilters: () => _view.unmodifiableFilters,
readContext: () => _view.filterContext,
isQueryConstraintBlocked: () => _view.isQueryConstraintBlocked,
replaceFilters: _replaceApiFilters,
replaceFiltersAsync: _replaceApiFiltersAsync,
replaceFiltersAndSorts: _replaceApiFiltersAndSorts,
replaceFiltersAndSortsAsync: _replaceApiFiltersAndSortsAsync,
);
sort = FdcDataSetSorts(
canApplyViewOperation: () => _canApplyViewOperation,
useAsyncViewOperations: () => _paging.enabled,
readSorts: () => _view.unmodifiableSorts,
normalizeSorts: _normalizeSorts,
replaceSorts: _replaceApiSorts,
replaceSortsAsync: _replaceApiSortsAsync,
);
search = FdcDataSetSearchApi.internal(
readState: () => _view.currentSearchState,
applySearch: _applySearch,
clearSearch: _clearSearch,
);
_rebuildView(notify: false);
}