Skip to content

Commit b03d81d

Browse files
feat: add field and form states
1 parent 4e3f364 commit b03d81d

File tree

5 files changed

+626
-315
lines changed

5 files changed

+626
-315
lines changed

lib/src/form_builder.dart

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,29 @@ typedef FormBuilderFields
102102
= Map<String, FormBuilderFieldState<FormBuilderField<dynamic>, dynamic>>;
103103

104104
class FormBuilderState extends State<FormBuilder> {
105-
final _formKey = GlobalKey<FormState>();
105+
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
106+
final FormBuilderFields _fields = {};
107+
final Map<String, dynamic> _instantValue = {};
108+
final Map<String, dynamic> _savedValue = {};
109+
// Because dart type system will not accept ValueTransformer<dynamic>
110+
final Map<String, Function> _transformers = {};
106111

107112
bool get enabled => widget.enabled;
108113

109-
final FormBuilderFields _fields = {};
114+
/// Verify if all fields on form are valid
115+
bool get isValid => fields.values.every((field) => field.isValid);
116+
117+
/// Verify if some field on form are dirty
118+
bool get isDirty => fields.values.any((field) => field.isDirty);
119+
120+
/// Verify if some field on form are touched
121+
bool get isTouched => fields.values.any((field) => field.isTouched);
110122

111-
//because dart type system will not accept ValueTransformer<dynamic>
112-
final _transformers = <String, Function>{};
113-
final _instantValue = <String, dynamic>{};
114-
final _savedValue = <String, dynamic>{};
123+
/// Get initialValue
124+
Map<String, dynamic> get initialValue => widget.initialValue;
125+
126+
/// Get all fields of form
127+
FormBuilderFields get fields => _fields;
115128

116129
Map<String, dynamic> get instantValue =>
117130
Map<String, dynamic>.unmodifiable(_instantValue.map((key, value) =>
@@ -122,11 +135,6 @@ class FormBuilderState extends State<FormBuilder> {
122135
Map<String, dynamic>.unmodifiable(_savedValue.map((key, value) =>
123136
MapEntry(key, _transformers[key]?.call(value) ?? value)));
124137

125-
/// Returns values after saving
126-
Map<String, dynamic> get initialValue => widget.initialValue;
127-
128-
FormBuilderFields get fields => _fields;
129-
130138
dynamic transformValue<T>(String name, T? v) {
131139
final t = _transformers[name];
132140
return t != null ? t.call(v) : v;
@@ -150,9 +158,6 @@ class FormBuilderState extends State<FormBuilder> {
150158
widget.onChanged?.call();
151159
}
152160

153-
bool get isValid =>
154-
fields.values.where((element) => !element.isValid).isEmpty;
155-
156161
void removeInternalFieldValue(
157162
String name, {
158163
required bool isSetState,
@@ -282,22 +287,15 @@ class FormBuilderState extends State<FormBuilder> {
282287
);
283288
}
284289

290+
/// Reset form to `initialValue`
285291
void reset() {
286-
_formKey.currentState!.reset();
287-
for (var field in _fields.entries) {
288-
try {
289-
field.value.didChange(getRawValue(field.key));
290-
} catch (e, st) {
291-
log(
292-
'Error when resetting field: ${field.key}',
293-
error: e,
294-
stackTrace: st,
295-
level: 2000,
296-
);
297-
}
298-
}
292+
_formKey.currentState?.reset();
299293
}
300294

295+
/// Update fields values of form.
296+
/// Useful when need update all values at once, after init.
297+
///
298+
/// To load all values at once on init, use `initialValue` property
301299
void patchValue(Map<String, dynamic> val) {
302300
val.forEach((key, dynamic value) {
303301
_fields[key]?.didChange(value);

lib/src/form_builder_field.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
7474
String? _customErrorText;
7575
FormBuilderState? _formBuilderState;
7676
bool _touched = false;
77+
bool _dirty = false;
7778
late FocusNode effectiveFocusNode;
7879
FocusAttachment? focusAttachment;
7980

@@ -105,6 +106,8 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
105106

106107
bool get enabled => widget.enabled && (_formBuilderState?.enabled ?? true);
107108
bool get _readOnly => !(_formBuilderState?.widget.skipDisabled ?? false);
109+
bool get isDirty => _dirty;
110+
bool get isTouched => _touched;
108111

109112
InputDecoration get decoration => widget.decoration.copyWith(
110113
errorText: widget.enabled || _readOnly
@@ -173,6 +176,7 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
173176

174177
void _informFormForFieldChange() {
175178
if (_formBuilderState != null) {
179+
_dirty = true;
176180
if (enabled || _readOnly) {
177181
_formBuilderState!.setInternalFieldValue<T>(
178182
widget.name,
@@ -212,7 +216,8 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
212216
@override
213217
void reset() {
214218
super.reset();
215-
setValue(initialValue);
219+
didChange(initialValue);
220+
_dirty = false;
216221
if (_customErrorText != null) {
217222
setState(() => _customErrorText = null);
218223
}

test/flutter_form_builder_test.dart

Lines changed: 0 additions & 235 deletions
This file was deleted.

0 commit comments

Comments
 (0)