@@ -71,49 +71,62 @@ class FormBuilder extends StatefulWidget {
71
71
class FormBuilderState extends State <FormBuilder > {
72
72
final _formKey = GlobalKey <FormState >();
73
73
74
- Map <String , FormBuilderFieldState > _fields ;
74
+ final _fields = < String , FormBuilderFieldState > {} ;
75
75
76
- Map <String , dynamic > _value ;
76
+ final _value = < String , dynamic > {} ;
77
77
78
78
Map <String , dynamic > get value => Map <String , dynamic >.unmodifiable (_value);
79
79
80
80
Map <String , dynamic > get initialValue => widget.initialValue;
81
81
82
82
Map <String , FormBuilderFieldState > get fields => _fields;
83
83
84
- @override
85
- void initState () {
86
- super .initState ();
87
- _fields = {};
88
- _value = < String , dynamic > {};
89
- }
90
-
91
- @override
92
- void dispose () {
93
- _fields = null ;
94
- super .dispose ();
95
- }
96
-
97
84
void setInternalFieldValue (String name, dynamic value) {
98
85
setState (() {
99
- _value = < String , dynamic > {..._value, name : value} ;
86
+ _value[name] = value;
100
87
});
101
88
}
102
89
103
90
void removeInternalFieldValue (String name) {
104
91
setState (() {
105
- _value = < String , dynamic > {..._value.. remove (name)} ;
92
+ _value. remove (name);
106
93
});
107
94
}
108
95
109
96
void registerField (String name, FormBuilderFieldState field) {
110
- assert (! _fields.containsKey (name));
97
+ // Each field must have a unique name. Ideally we could simply:
98
+ // assert(!_fields.containsKey(name));
99
+ // However, Flutter will delay dispose of deactivated fields, so if a
100
+ // field is being replaced, the new instance is registered before the old
101
+ // one is unregistered. To accommodate that use case, but also provide
102
+ // assistance to accidental duplicate names, we check and emit a warning.
103
+ assert (() {
104
+ if (_fields.containsKey (name)) {
105
+ print ('Warning! Replacing duplicate Field for $name '
106
+ ' -- this is OK to ignore as long as the field was intentionally replaced' );
107
+ }
108
+ return true ;
109
+ }());
111
110
_fields[name] = field;
112
111
}
113
112
114
- void unregisterField (String name) {
113
+ void unregisterField (String name, FormBuilderFieldState field ) {
115
114
assert (_fields.containsKey (name));
116
- _fields.remove (name);
115
+ // Only remove the field when it is the one registered. It's possible that
116
+ // the field is replaced (registerField is called twice for a given name)
117
+ // before unregisterField is called for the name, so just emit a warning
118
+ // since it may be intentional.
119
+ if (field == _fields[name]) {
120
+ _fields.remove (name);
121
+ } else {
122
+ assert (() {
123
+ // This is OK to ignore when you are intentionally replacing a field
124
+ // with another field using the same name.
125
+ print ('Warning! Ignoring Field unregistration for $name '
126
+ ' -- this is OK to ignore as long as the field was intentionally replaced' );
127
+ return true ;
128
+ }());
129
+ }
117
130
}
118
131
119
132
void save () {
0 commit comments