diff --git a/lib/src/form/src/controller.dart b/lib/src/form/src/controller.dart index 65d4893..9e44af9 100644 --- a/lib/src/form/src/controller.dart +++ b/lib/src/form/src/controller.dart @@ -21,10 +21,12 @@ import 'models/form_group_value.model.dart'; class AstromicFormController extends FormController { AstromicFormController({ Map? initialValues, + Map? initialHostedValues, this.errorStream, }) : super(initialValues) { - // Add states and messages based on initial controller. + // Add states and messages based on initial controllers. _addInitialControllers(initialValues); + _addInitialHostedValues(initialHostedValues); } //SECTION - Overrides @@ -254,12 +256,21 @@ class AstromicFormController extends FormController { for (final String fieldID in structure.fields) { final String fullID = standeredGroupFormat(baseID, index.toString(), fieldID); - controller(fullID); + String? preFilled; + if (structure.preFields?.containsKey(fieldID) ?? false) { + preFilled = structure.preFields![fieldID]; + } + controller(fullID, initialText: preFilled); } for (final String valueID in structure.values ?? []) { final String fullID = standeredGroupFormat(baseID, index.toString(), valueID); - controller(fullID); + (String, dynamic)? preFilled; + if (structure.preValues?.containsKey(valueID) ?? false) { + preFilled = structure.preValues![valueID]; + } + controller(fullID, initialText: preFilled?.$1); + setValue(valueID, preFilled?.$2); } } @@ -548,5 +559,13 @@ class AstromicFormController extends FormController { ))); } } + + void _addInitialHostedValues(Map? initialValues) { + if (initialValues != null) { + for (MapEntry vEntry in initialValues.entries) { + setValue(vEntry.key, vEntry.value.$1, isRequired: vEntry.value.$2); + } + } + } //!SECTION } diff --git a/lib/src/form/src/models/form_group_structure.model.dart b/lib/src/form/src/models/form_group_structure.model.dart index 2b825c4..22b6604 100644 --- a/lib/src/form/src/models/form_group_structure.model.dart +++ b/lib/src/form/src/models/form_group_structure.model.dart @@ -5,25 +5,33 @@ import 'package:flutter/foundation.dart'; class FormGroupStructure { final String id; final List fields; + final Map? preFields; final List? values; + final Map? preValues; final List<(int initialCount, FormGroupStructure structure)>? subGroups; FormGroupStructure({ required this.id, required this.fields, this.values, + this.preFields, + this.preValues, this.subGroups, }); FormGroupStructure copyWith({ String? id, List? fields, + Map? preFields, List? values, + Map? preValues, List<(int initialCount, FormGroupStructure structure)>? subGroups, }) { return FormGroupStructure( id: id ?? this.id, fields: fields ?? this.fields, values: values ?? this.values, + preFields: preFields ?? this.preFields, + preValues: preValues ?? this.preValues, subGroups: subGroups ?? this.subGroups, ); } @@ -33,6 +41,8 @@ class FormGroupStructure { 'id': id, 'fields': fields, 'values': values, + 'preFields': preFields, + 'preValues': preValues, 'subGroups': subGroups?.map(((int initialCount, FormGroupStructure structure) x) => {'structure': x.$2.toMap(), 'initialCount': x.$1}).toList(), }; } @@ -42,6 +52,8 @@ class FormGroupStructure { id: map['id'] as String, fields: List.from(map['fields'] as List), values: map['values'] != null ? List.from(map['values'] as List) : null, + preFields: map['preFields'] != null ? map['preFields'] as Map : null, + preValues: map['preValues'] != null ? map['preValues'] as Map: null, subGroups: map['subGroups'] != null ? (map['subGroups'] as List>).map((Map map) => (int.tryParse(map['initialCount']) ?? 0, FormGroupStructure.fromMap(map['structure']))).toList() : null, @@ -54,18 +66,23 @@ class FormGroupStructure { @override String toString() { - return 'FormGroupStructure(id: $id, fields: $fields, values: $values, subGroups: $subGroups)'; + return 'FormGroupStructure(id: $id, fields: $fields, values: $values, preFields: $preFields, preValues: $preValues, subGroups: $subGroups)'; } @override bool operator ==(covariant FormGroupStructure other) { if (identical(this, other)) return true; - return other.id == id && listEquals(other.fields, fields) && listEquals(other.values, values) && listEquals(other.subGroups, subGroups); + return other.id == id && + listEquals(other.fields, fields) && + listEquals(other.values, values) && + mapEquals(other.preFields, preFields) && + mapEquals(other.preValues, preValues) && + listEquals(other.subGroups, subGroups); } @override int get hashCode { - return id.hashCode ^ fields.hashCode ^ values.hashCode ^ subGroups.hashCode; + return id.hashCode ^ fields.hashCode ^ values.hashCode ^ preFields.hashCode ^ preValues.hashCode ^ subGroups.hashCode; } } diff --git a/lib/src/presenting/src/widgets/future_presenter.widget.dart b/lib/src/presenting/src/widgets/future_presenter.widget.dart index fcdb02f..d9747c4 100644 --- a/lib/src/presenting/src/widgets/future_presenter.widget.dart +++ b/lib/src/presenting/src/widgets/future_presenter.widget.dart @@ -21,6 +21,7 @@ class AstromicFuturePresenter extends StatefulWidget { //SECTION - Widget Arguments final AstromicPresenterController controller; final String id; + final Map? neededArguments; // final Map? r)> stateBuilder; final AstromicPresenterConfiguration? configuration; @@ -32,6 +33,8 @@ class AstromicFuturePresenter extends StatefulWidget { required this.id, required this.stateBuilder, this.configuration, + this.neededArguments, + }); @override @@ -62,8 +65,8 @@ class _AstromicFuturePresenterState extends State> //s1 --State // //s1 --Controllers & Listeners - widget.controller.getRefreshStream(widget.id).listen((_) { - _refreshFuture(); // Force future recreation on refresh + widget.controller.getRefreshStream(widget.id).listen((uA) { + _refreshFuture(updatedArgs: uA); // Force future recreation on refresh }); //s1 --Controllers & Listeners // @@ -120,16 +123,17 @@ class _AstromicFuturePresenterState extends State> } //S1 -- Method to reinitialize or update `_future` with a new instance - void _refreshFuture() { + void _refreshFuture({Map? updatedArgs}) { // Increment the refresh key to ensure a unique future instance _refreshKey++; setState(() { - _initializeFuture(); + _initializeFuture(updatedArgs: updatedArgs); }); } //S1 -- Method to reinitialize or update `_future` with a new instance - void _initializeFuture() { + void _initializeFuture({Map? updatedArgs}) { + widget.controller.setProvidedArguments(updatedArgs ?? widget.neededArguments ?? {}); _future = widget.controller.getFuture(widget.id)?.then((dynamic result) => result as T?); } //!SECTION diff --git a/lib/src/presenting/src/widgets/presenter_controller.widget.dart b/lib/src/presenting/src/widgets/presenter_controller.widget.dart index 11330ea..d78c74f 100644 --- a/lib/src/presenting/src/widgets/presenter_controller.widget.dart +++ b/lib/src/presenting/src/widgets/presenter_controller.widget.dart @@ -3,17 +3,17 @@ import 'dart:async'; /// A contrller used to control Futures/Streams to present them effeciantly. class AstromicPresenterController { - late final Map _futures; + late final Map args)? fetch, int c)> _futures; late final Map args)?> _streams; - late final Map> _futureRefreshers; + late final Map?>> _futureRefreshers; AstromicPresenterController({ - Map futures = const {}, + Map args)? fetch, int startCycle)> futures = const {}, Map args)?> streams = const {}, }) : _futures = futures.map((k, v) => MapEntry(k, (v.$1, v.$2))), - _futureRefreshers = futures.map((k, v) => MapEntry(k, StreamController.broadcast())), + _futureRefreshers = futures.map((k, v) => MapEntry(k, StreamController?>.broadcast())), _streams = streams; Map providedArguments = {}; @@ -35,7 +35,7 @@ class AstromicPresenterController { Future? getFuture(String id) { assert(_futures.containsKey(id), 'did you add a future with this id?'); - return _futures[id]!.$1!() as Future?; + return _futures[id]!.$1!(getProvidedArguments()) as Future?; } /// Get the stream using it's ID. @@ -46,7 +46,7 @@ class AstromicPresenterController { } /// Get the refresh stream of a future using it's ID. - Stream getRefreshStream(String id) { + Stream?> getRefreshStream(String id) { assert(_futures.containsKey(id), 'did you add a future with this id?'); return _futureRefreshers[id]!.stream; @@ -60,10 +60,10 @@ class AstromicPresenterController { } /// Refresh a future using it's ID. - void refreshFuture(String id) { + void refreshFuture(String id, {Map? updatedArgs}) { assert(_futures.containsKey(id), 'did you add a future with this id?'); - _futureRefreshers[id]!.add(null); + _futureRefreshers[id]!.add(updatedArgs); } /// Dispose of a future using it's ID. diff --git a/lib/src/sheet/sheet_helper.astromic.dart b/lib/src/sheet/sheet_helper.astromic.dart index 9a274b3..d5a1a28 100644 --- a/lib/src/sheet/sheet_helper.astromic.dart +++ b/lib/src/sheet/sheet_helper.astromic.dart @@ -124,7 +124,7 @@ class AstromicSheetHelper { radius: sheetStyle.radius, // child: ChangeNotifierProvider( - create: (BuildContext c) => SheetStore(), + create: (BuildContext c) => store, child: BaseSheetWidget( sheetType: SheetType.form, // @@ -202,7 +202,7 @@ class AstromicSheetHelper { // s2 -- Child builder: (BuildContext context, ScrollController scrollController, ScrollPhysics scrollPhysics, int stop) { return ChangeNotifierProvider( - create: (BuildContext c) => SheetStore(), + create: (BuildContext c) => store, child: BaseSheetWidget( sheetType: SheetType.scroller, sheetConfiguration: sheetConfigs, diff --git a/lib/src/sheet/src/models/sheet_store.model.dart b/lib/src/sheet/src/models/sheet_store.model.dart index a375d2e..84cc2e7 100644 --- a/lib/src/sheet/src/models/sheet_store.model.dart +++ b/lib/src/sheet/src/models/sheet_store.model.dart @@ -1,3 +1,6 @@ +// ignore_for_file: close_sinks + +import 'dart:async'; import 'dart:collection'; import 'package:flutter/widgets.dart'; @@ -9,6 +12,24 @@ class SheetStore extends ChangeNotifier { /// An unmodifiable view of the items in the store. UnmodifiableMapView get items => UnmodifiableMapView(_items); + static final StreamController> _stateStreamController = StreamController>.broadcast(); + final Stream> stateStream = _stateStreamController.stream; + + /// Adds [item] to store. + dynamic get(String itemID) { + if (!_items.containsKey(itemID)) { + throw Exception('No item with the ID $itemID exist in the SheetStore, Are you sure you added it?'); + } + return _items[itemID]; + } + + dynamic tryGet(String itemID) { + if (!_items.containsKey(itemID)) { + return null; + } + return _items[itemID]; + } + /// Adds [item] to store. void add(String itemID, dynamic value) { _items.addEntries(>[MapEntry(itemID, value)]); @@ -17,21 +38,25 @@ class SheetStore extends ChangeNotifier { } /// Updates [item] in the store. - void update(String itemID, dynamic value) { + void update(String itemID, dynamic value, {bool addIfAbsent = false}) { if (!_items.containsKey(itemID)) { - throw Exception('No item with the ID $itemID exist in the SheetStore, Are you sure you added it?'); + if (addIfAbsent) { + add(itemID, value); + } else { + throw Exception('No item with the ID $itemID exist in the SheetStore, Are you sure you added it?'); + } + } else { + _items[itemID] = value; } - _items[itemID] = value; // This call tells the widgets that are listening to this store to rebuild. notifyListeners(); } /// Removes [item] from the store. void remove(String itemID, dynamic value) { - if (!_items.containsKey(itemID)) { - throw Exception('No item with the ID $itemID exist in the SheetStore, Are you sure you added it?'); + if (_items.containsKey(itemID)) { + _items.remove(itemID); } - _items.remove(itemID); // This call tells the widgets that are listening to this store to rebuild. notifyListeners(); }