This commit is contained in:
2025-03-23 15:46:57 +02:00
parent 0a08c573f4
commit e25b3b811e
3 changed files with 153 additions and 30 deletions

View File

@@ -1,4 +1,5 @@
export 'package:form_controller/form_controller.dart';
export 'src/controller.dart';
export 'src/form_field.dart';
export 'src/form_value_wrapper.dart';
export 'src/enums/enums.exports.dart';

View File

@@ -1,5 +1,7 @@
//s1 Imports
//s2 Core Package Imports
// ignore_for_file: close_sinks
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:flutter/scheduler.dart';
@@ -18,13 +20,17 @@ class AstromicFormController extends FormController {
// State Variables
final Map<String, AstromicFieldState> fieldStates = <String, AstromicFieldState>{};
final Map<String, String?> fieldMessages = <String, String?>{};
final Map<String, dynamic> _hostedValues = <String, dynamic>{};
final Map<String, (dynamic, bool)> _hostedValues = <String, (dynamic, bool)>{};
// final Map<String, Map<String, String>>? streamedErrorMaps; // fieldId: {errorCode: errorMessage}
final Stream<List<(String internalCode,String? message)>>? errorStream;
final Stream<List<(String internalCode, String? message)>>? errorStream;
// State Stream Variables
static final StreamController<(String, AstromicFieldState)> _stateStreamController = StreamController<(String id, AstromicFieldState)>.broadcast();
final Stream<(String id, AstromicFieldState)> stateStream = _stateStreamController.stream;
// Hosted Value Validation Stream Variables
static final StreamController<(String, bool)> _hostedValueValidationStreamController = StreamController<(String id, bool)>.broadcast();
final Stream<(String id, bool isValidationErrored)> hostedValueValidationStream = _hostedValueValidationStreamController.stream;
AstromicFormController({
Map<String, (String initialText, bool initialObscurity)>? extraControllers,
// this.streamedErrorMaps,
@@ -35,7 +41,7 @@ class AstromicFormController extends FormController {
// Listen on the error stream for values and push to the corresponding field state.
// if (errorStream != null) {
// _handleErrorStream();
// _handleErrorStream();
// }
}
@@ -63,20 +69,32 @@ class AstromicFormController extends FormController {
setState(fieldId, AstromicFieldState.idle);
}
/// Set the value of a hosted state variable using it's ID.
void setValue<T>(String id, T data) {
if (_hostedValues.keys.toList().contains(id)) {
_hostedValues[id] = data;
} else {
_hostedValues.addEntries(<MapEntry<String, dynamic>>[MapEntry<String, dynamic>(id, data)]);
bool validateValues(List<String> valueIDs) {
for (String hostedValueID in valueIDs) {
if (_hostedValues.containsKey(hostedValueID) && _hostedValues[hostedValueID]!.$2 && _hostedValues[hostedValueID]!.$1 == null) {
// Validation Error!
_hostedValueValidationStreamController.add((hostedValueID, true));
return false;
}
}
return true;
}
/// Set the value of a hosted state variable using it's ID.
void setValue<T>(String id, T data, {bool isRequired = false}) {
if (_hostedValues.keys.toList().contains(id)) {
_hostedValues[id] = (data, isRequired);
} else {
_hostedValues.addEntries(<MapEntry<String, (dynamic, bool)>>[MapEntry<String, (dynamic, bool)>(id, (data, isRequired))]);
}
_hostedValueValidationStreamController.add((id, false));
}
/// Get the value of a hosted state variable using it's ID.
T? getValue<T>(String id) {
if (_hostedValues.keys.toList().contains(id)) {
if (_hostedValues[id] is T) {
return _hostedValues[id];
if (_hostedValues[id] is (T?, bool)) {
return _hostedValues[id]?.$1;
} else {
throw FlutterError('Value found but is not of the type $T');
}
@@ -123,24 +141,5 @@ class AstromicFormController extends FormController {
)) ??
<MapEntry<String, String?>>{});
}
// _handleErrorStream() {
// errorStream!.distinct().listen((List<String> errorCodes) {
// if (streamedErrorMaps != null && streamedErrorMaps!.isNotEmpty) {
// for (String errorMapId in streamedErrorMaps!.keys.toList()) {
// if (super.controllers != null && super.controllers!.containsKey(errorMapId)) {
// if (streamedErrorMaps![errorMapId] != null &&
// streamedErrorMaps![errorMapId]!.isNotEmpty &&
// streamedErrorMaps![errorMapId]!.keys.toList().where((String k) => errorCodes.contains(k)).toList().isNotEmpty) {
// for (String eC in streamedErrorMaps![errorMapId]!.keys.toList().where((String k) => errorCodes.contains(k)).toList()) {
// String? m = streamedErrorMaps![errorMapId]![eC];
// setState(errorMapId, AstromicFieldState.withError, message: m ?? 'Error Message was not set!');
// }
// }
// }
// }
// }
// });
// }
//!SECTION
}

View File

@@ -0,0 +1,123 @@
//s1 Imports
//s2 Packages
//s3 Core Packages
import 'package:flutter/material.dart';
import '../../sheet/sheet_helper.astromic.dart';
//s3 Internal Packages
//s3 3rd-party Packages
//s2 Utility
//s3 Configs
//s3 Misc
//s2 Domain
//s3 Entities
//s3 Usecases
//s2 Presentation
//s3 Design
//s3 Presenters
//s3 Widgets
//s1 Exports
class FormValueWrapper<T extends Object?> extends StatefulWidget {
//SECTION - Widget Arguments
final AstromicFormController controller;
final String id;
final Widget Function(T? value, bool isErroredForValidation, void Function(T value, bool isRequired) valueSetter) builder;
//!SECTION
//
const FormValueWrapper({
super.key,
required this.controller,
required this.id,
required this.builder,
});
@override
State<FormValueWrapper<T>> createState() => _FormValueWrapperState<T>();
}
class _FormValueWrapperState<T> extends State<FormValueWrapper<T>> {
//
//SECTION - State Variables
//s1 --State
//s1 --State
//
//s1 --Controllers
// late AstromicFormController _formController;
//s1 --Controllers
//
//s1 --Constants
//s1 --Constants
//!SECTION
@override
void initState() {
super.initState();
//
//SECTION - State Variables initializations & Listeners
//s1 --State
//s1 --State
//
//s1 --Controllers & Listeners
// _formController = widget.controller;
//s1 --Controllers & Listeners
//
//s1 --Late & Async Initializers
//s1 --Late & Async Initializers
//!SECTION
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
//
//SECTION - State Variables initializations & Listeners
//s1 --State
//s1 --State
//
//s1 --Controllers & Listeners
//s1 --Controllers & Listeners
//
//!SECTION
}
//SECTION - Dumb Widgets
//!SECTION
//SECTION - Stateless functions
//!SECTION
//SECTION - Action Callbacks
//!SECTION
@override
Widget build(BuildContext context) {
//SECTION - Build Setup
//s1 --Values
//double w = MediaQuery.of(context).size.width;
//double h = MediaQuery.of(context).size.height;
//s1 --Values
//
//s1 --Contexted Widgets
//s1 --Contexted Widgets
//!SECTION
//SECTION - Build Return
return StreamBuilder<(String, bool)>(
stream: widget.controller.hostedValueValidationStream,
builder: (BuildContext context, AsyncSnapshot<(String, bool)> validationSnapshot) {
return widget.builder(widget.controller.getValue(widget.id),
validationSnapshot.hasData && validationSnapshot.data != null && validationSnapshot.data!.$1 == widget.id && validationSnapshot.data!.$2 ? true : false, (T newValue, bool isRequired) {
return widget.controller.setValue(widget.id, (newValue, isRequired));
});
});
//!SECTION
}
@override
void dispose() {
//SECTION - Disposable variables
//!SECTION
super.dispose();
}
}