Skip to content

Commit b6424d4

Browse files
Merge pull request #1228 from flutter-form-builder-ecosystem/add-states-617
Add field and form states
2 parents 4e3f364 + 1b9ee80 commit b6424d4

File tree

7 files changed

+640
-318
lines changed

7 files changed

+640
-318
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ This package helps in creation of data collection forms in Flutter by removing t
55
Also included are common ready-made form input fields for FormBuilder. This gives you a convenient way of adding common ready-made input fields instead of creating your own FormBuilderField from scratch.
66

77
[![Pub Version](https://img.shields.io/pub/v/flutter_form_builder?logo=flutter&style=for-the-badge)](https://pub.dev/packages/flutter_form_builder)
8-
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/flutter-form-builder-ecosystem/flutter_form_builder/Base?logo=github&style=for-the-badge)](https://github.com/flutter-form-builder-ecosystem/flutter_form_builder/actions/workflows/base.yaml)
8+
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/flutter-form-builder-ecosystem/flutter_form_builder/base.yaml?branch=main&logo=github&style=for-the-badge)](https://github.com/flutter-form-builder-ecosystem/flutter_form_builder/actions/workflows/base.yaml)
99
[![Codecov](https://img.shields.io/codecov/c/github/flutter-form-builder-ecosystem/flutter_form_builder?logo=codecov&style=for-the-badge)](https://codecov.io/gh/flutter-form-builder-ecosystem/flutter_form_builder/)
1010
[![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/flutter-form-builder-ecosystem/flutter_form_builder?logo=codefactor&style=for-the-badge)](https://www.codefactor.io/repository/github/flutter-form-builder-ecosystem/flutter_form_builder)
1111
___

lib/src/form_builder.dart

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'dart:developer';
2-
31
import 'package:flutter/material.dart';
42
import 'package:flutter_form_builder/flutter_form_builder.dart';
53

@@ -102,16 +100,33 @@ typedef FormBuilderFields
102100
= Map<String, FormBuilderFieldState<FormBuilderField<dynamic>, dynamic>>;
103101

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

107110
bool get enabled => widget.enabled;
108111

109-
final FormBuilderFields _fields = {};
112+
/// Verify if all fields on form are valid.
113+
bool get isValid => fields.values.every((field) => field.isValid);
114+
115+
/// Will be true if some field on form are dirty.
116+
///
117+
/// Dirty: The value of field is changed by user or by logic code.
118+
bool get isDirty => fields.values.any((field) => field.isDirty);
119+
120+
/// Will be true if some field on form are touched.
121+
///
122+
/// Touched: The field is focused by user or by logic code.
123+
bool get isTouched => fields.values.any((field) => field.isTouched);
124+
125+
/// Get initialValue.
126+
Map<String, dynamic> get initialValue => widget.initialValue;
110127

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>{};
128+
/// Get all fields of form.
129+
FormBuilderFields get fields => _fields;
115130

116131
Map<String, dynamic> get instantValue =>
117132
Map<String, dynamic>.unmodifiable(_instantValue.map((key, value) =>
@@ -122,11 +137,6 @@ class FormBuilderState extends State<FormBuilder> {
122137
Map<String, dynamic>.unmodifiable(_savedValue.map((key, value) =>
123138
MapEntry(key, _transformers[key]?.call(value) ?? value)));
124139

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

153-
bool get isValid =>
154-
fields.values.where((element) => !element.isValid).isEmpty;
155-
156163
void removeInternalFieldValue(
157164
String name, {
158165
required bool isSetState,
@@ -282,22 +289,15 @@ class FormBuilderState extends State<FormBuilder> {
282289
);
283290
}
284291

292+
/// Reset form to `initialValue`
285293
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-
}
294+
_formKey.currentState?.reset();
299295
}
300296

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

lib/src/form_builder_field.dart

Lines changed: 14 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

@@ -106,6 +107,16 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
106107
bool get enabled => widget.enabled && (_formBuilderState?.enabled ?? true);
107108
bool get _readOnly => !(_formBuilderState?.widget.skipDisabled ?? false);
108109

110+
/// Will be true if the field is dirty
111+
///
112+
/// The value of field is changed by user or by logic code.
113+
bool get isDirty => _dirty;
114+
115+
/// Will be true if the field is touched
116+
///
117+
/// The field is focused by user or by logic code
118+
bool get isTouched => _touched;
119+
109120
InputDecoration get decoration => widget.decoration.copyWith(
110121
errorText: widget.enabled || _readOnly
111122
? widget.decoration.errorText ?? errorText
@@ -173,6 +184,7 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
173184

174185
void _informFormForFieldChange() {
175186
if (_formBuilderState != null) {
187+
_dirty = true;
176188
if (enabled || _readOnly) {
177189
_formBuilderState!.setInternalFieldValue<T>(
178190
widget.name,
@@ -212,7 +224,8 @@ class FormBuilderFieldState<F extends FormBuilderField<T>, T>
212224
@override
213225
void reset() {
214226
super.reset();
215-
setValue(initialValue);
227+
didChange(initialValue);
228+
_dirty = false;
216229
if (_customErrorText != null) {
217230
setState(() => _customErrorText = null);
218231
}

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ description: This package helps in creation of forms in Flutter by removing the
33
version: 7.8.0
44
repository: https://github.com/flutter-form-builder-ecosystem/flutter_form_builder
55
issue_tracker: https://github.com/flutter-form-builder-ecosystem/flutter_form_builder/issues
6+
homepage: https://github.com/flutter-form-builder-ecosystem
67
funding:
78
- https://opencollective.com/flutter-form-builder-ecosystem
89

test/flutter_form_builder_test.dart

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

0 commit comments

Comments
 (0)