@@ -33,4 +33,141 @@ void main() {
33
33
expect (formSave (), isTrue);
34
34
expect (formValue (textFieldName), isEmpty);
35
35
});
36
+
37
+ testWidgets (
38
+ 'FormBuilder Dynamic Field -- keeping value' ,
39
+ (WidgetTester tester) async {
40
+ const String testWidgetName = 'test_widget_name' ;
41
+
42
+ await tester.pumpWidget (
43
+ buildTestableFieldWidget (
44
+ _DynamicFormFields (
45
+ name: testWidgetName,
46
+ valueTransformer: (value) {
47
+ return value is String ? int .tryParse (value) : null ;
48
+ },
49
+ ),
50
+ // the value is kept
51
+ clearValueOnUnregister: false ,
52
+ ),
53
+ );
54
+
55
+ // Write an input and test the transformer
56
+ formFieldDidChange (testWidgetName, '1' );
57
+ expect (int , formInstantValue (testWidgetName).runtimeType);
58
+ expect (1 , formInstantValue (testWidgetName));
59
+
60
+ // Remove the dynamic field from the widget tree
61
+ final _DynamicFormFieldsState dynamicFieldState =
62
+ tester.state (find.byType (_DynamicFormFields ));
63
+ dynamicFieldState.show = false ;
64
+
65
+ // Pump the next frame, disposing the field's state
66
+ await tester.pump ();
67
+
68
+ // With the field unregistered, the form does not have its transformer
69
+ // but it still has its value, now recovered as type String
70
+ expect (String , formInstantValue (testWidgetName).runtimeType);
71
+ expect ('1' , formInstantValue (testWidgetName));
72
+
73
+ // Show and recreate the field's state
74
+ dynamicFieldState.show = true ;
75
+ await tester.pump ();
76
+
77
+ // The transformer is registered again and with the internal value that
78
+ // was kept, it's expected an int of value 1
79
+ expect (int , formInstantValue (testWidgetName).runtimeType);
80
+ expect (1 , formInstantValue (testWidgetName));
81
+ },
82
+ );
83
+
84
+ testWidgets (
85
+ 'FormBuilder Dynamic Field -- clearing value' ,
86
+ (WidgetTester tester) async {
87
+ const String testWidgetName = 'test_widget_name' ;
88
+
89
+ await tester.pumpWidget (
90
+ buildTestableFieldWidget (
91
+ _DynamicFormFields (
92
+ name: testWidgetName,
93
+ valueTransformer: (value) {
94
+ return value is String ? int .tryParse (value) : null ;
95
+ },
96
+ ),
97
+ // the value is cleared
98
+ clearValueOnUnregister: true ,
99
+ ),
100
+ );
101
+
102
+ // Write an input and test the transformer
103
+ formFieldDidChange (testWidgetName, '1' );
104
+ await tester.pump ();
105
+ expect (int , formInstantValue (testWidgetName).runtimeType);
106
+ expect (1 , formInstantValue (testWidgetName));
107
+
108
+ // Remove the dynamic field from the widget tree
109
+ final _DynamicFormFieldsState dynamicFieldState =
110
+ tester.state (find.byType (_DynamicFormFields ));
111
+ dynamicFieldState.show = false ;
112
+
113
+ // Pump the next frame, disposing the field's state
114
+ await tester.pump ();
115
+
116
+ // With the field unregistered, the form does not have its transformer,
117
+ // and since the value was cleared, neither its value
118
+ expect (Null , formInstantValue (testWidgetName).runtimeType);
119
+ expect (null , formInstantValue (testWidgetName));
120
+
121
+ // Show and recreate the field's state
122
+ dynamicFieldState.show = true ;
123
+ await tester.pump ();
124
+
125
+ // A new input is needed to get another value
126
+ formFieldDidChange (testWidgetName, '2' );
127
+ await tester.pump ();
128
+ expect (int , formInstantValue (testWidgetName).runtimeType);
129
+ expect (2 , formInstantValue (testWidgetName));
130
+ },
131
+ );
132
+ }
133
+
134
+ // simple stateful widget that can hide and show its child with the intent of
135
+ // disposing it from the tree
136
+ class _DynamicFormFields extends StatefulWidget {
137
+ const _DynamicFormFields ({
138
+ Key ? key,
139
+ required this .name,
140
+ this .valueTransformer,
141
+ }) : super (key: key);
142
+
143
+ final String name;
144
+ final ValueTransformer ? valueTransformer;
145
+
146
+ @override
147
+ State <_DynamicFormFields > createState () => _DynamicFormFieldsState ();
148
+ }
149
+
150
+ class _DynamicFormFieldsState extends State <_DynamicFormFields > {
151
+ bool _show = true ;
152
+
153
+ bool get show => _show;
154
+
155
+ set show (bool value) => setState (() => _show = value);
156
+
157
+ @override
158
+ Widget build (BuildContext context) {
159
+ return Visibility (
160
+ visible: _show,
161
+ maintainState: false ,
162
+ child: FormBuilderField (
163
+ name: widget.name,
164
+ valueTransformer: widget.valueTransformer,
165
+ builder: (FormFieldState <String ?> field) {
166
+ return TextField (
167
+ onChanged: (value) => field.didChange (value),
168
+ );
169
+ },
170
+ ),
171
+ );
172
+ }
36
173
}
0 commit comments