Last active
November 2, 2020 19:13
-
-
Save zs-dima/1a131d5dc06839655aadcd0a9526b028 to your computer and use it in GitHub Desktop.
form_data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/widgets.dart'; | |
class FormData<FormDataType> { | |
FormDataType data; | |
final List<FormEntry> _fields = <FormEntry>[]; | |
FormData({@required this.data}); | |
FormEntry add<FieldType>( | |
FieldType value, { | |
FormDataType Function(FieldType value) onSaved, | |
String Function(FieldType value) validator, | |
FocusNode focusNode, | |
}) { | |
final field = FormEntry( | |
initialValue: value, | |
onSaved: (v) { | |
if (onSaved != null) data = onSaved(v); | |
}, | |
validator: validator, | |
); | |
_fields.add(field); | |
return field; | |
} | |
void nextEmpty() { | |
final fieldNode = _fields.firstWhere((field) => !field.filled, orElse: () => null)?.focusNode; | |
if (fieldNode == null) { | |
unfocusAll(); | |
//_buttonFocusNode.requestFocus(); | |
} else { | |
fieldNode.requestFocus(); | |
} | |
} | |
void valid() => _fields.every((field) => field.validator(field.value) == null); | |
void unfocusAll() => _fields.map<FocusNode>((field) => field.focusNode).forEach((node) => node.unfocus()); | |
void setValidationStatus() => _fields.every((field) => field.filled); | |
FormDataType submit(BuildContext context) { | |
unfocusAll(); | |
final form = Form.of(context)..save(); | |
if (!form.validate()) { | |
nextEmpty(); | |
return null; | |
} | |
return data; | |
} | |
void dispose() { | |
for (final field in _fields) { | |
field.dispose(); | |
} | |
} | |
} | |
/// Form field proxy | |
@immutable | |
class FormEntry<FieldType> { | |
final FieldType initialValue; | |
FieldType get value => FieldType == String ? (_controller as TextEditingController).value.text : _controller.value; | |
set value(FieldType newValue) => _controller.value = newValue; | |
final FocusNode focusNode; | |
/// Check if field filled | |
bool get filled => !hasValidator || _onSaved == null || validator(value) == null; | |
/// On Form saved | |
ValueChanged<FieldType> get onSaved => _onSaved; | |
final ValueChanged<FieldType> _onSaved; | |
/// On field change | |
ValueChanged<FieldType> get onChanged => (dynamic value) => _controller.value = value; | |
/// Field validation | |
FormFieldValidator<FieldType> get validator => (dynamic value) => hasValidator ? _validator(value) : null; | |
final String Function(FieldType value) _validator; | |
/// If validator set | |
final bool hasValidator; | |
final ValueNotifier _controller; | |
ValueNotifier<T> controller<T>() => _controller as ValueNotifier<T>; | |
void addListener(VoidCallback listener) => _controller.addListener(listener); | |
void removeListener(VoidCallback listener) => _controller.removeListener(listener); | |
void dispose() { | |
_controller.dispose(); | |
} | |
FormEntry({ | |
@required this.initialValue, | |
@required ValueChanged<FieldType> onSaved, | |
String Function(FieldType value) validator, | |
FocusNode focusNode, | |
}) : focusNode = focusNode ?? FocusNode(), | |
_onSaved = onSaved, | |
_validator = validator, | |
hasValidator = validator != null, | |
_controller = FieldType == String ? TextEditingController(text: initialValue as String) : ValueNotifier<FieldType>(initialValue); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment