1
1
import 'package:flutter/material.dart' ;
2
+ import 'package:flutter_form_builder/flutter_form_builder.dart' ;
2
3
import 'package:flutter_localizations/flutter_localizations.dart' ;
3
4
import 'package:form_builder_validators/form_builder_validators.dart' ;
4
-
5
- import 'home_page.dart' ;
5
+ import 'package:intl/intl.dart' ;
6
6
7
7
void main () => runApp (const MyApp ());
8
8
@@ -14,28 +14,323 @@ class MyApp extends StatelessWidget {
14
14
return MaterialApp (
15
15
title: 'Flutter FormBuilder Demo' ,
16
16
debugShowCheckedModeBanner: false ,
17
- theme: ThemeData (
18
- primarySwatch: Colors .blue,
19
- inputDecorationTheme: const InputDecorationTheme (
20
- labelStyle: TextStyle (color: Colors .blueAccent),
21
- ),
22
- ),
23
17
localizationsDelegates: const [
24
18
FormBuilderLocalizations .delegate,
25
19
GlobalMaterialLocalizations .delegate,
26
20
GlobalWidgetsLocalizations .delegate,
27
21
],
28
- supportedLocales: const [
29
- Locale ('en' , '' ),
30
- Locale ('es' , '' ),
31
- Locale ('fa' , '' ),
32
- Locale ('fr' , '' ),
33
- Locale ('ja' , '' ),
34
- Locale ('pt' , '' ),
35
- Locale ('sk' , '' ),
36
- Locale ('pl' , '' ),
37
- ],
38
- home: const HomePage (),
22
+ supportedLocales: FormBuilderLocalizations .delegate.supportedLocales,
23
+ home: const CompleteForm (),
24
+ );
25
+ }
26
+ }
27
+
28
+ class CompleteForm extends StatefulWidget {
29
+ const CompleteForm ({Key ? key}) : super (key: key);
30
+
31
+ @override
32
+ CompleteFormState createState () {
33
+ return CompleteFormState ();
34
+ }
35
+ }
36
+
37
+ class CompleteFormState extends State <CompleteForm > {
38
+ bool autoValidate = true ;
39
+ bool readOnly = false ;
40
+ bool showSegmentedControl = true ;
41
+ final _formKey = GlobalKey <FormBuilderState >();
42
+ bool _ageHasError = false ;
43
+ bool _genderHasError = false ;
44
+
45
+ var genderOptions = ['Male' , 'Female' , 'Other' ];
46
+
47
+ void _onChanged (dynamic val) => debugPrint (val.toString ());
48
+
49
+ @override
50
+ Widget build (BuildContext context) {
51
+ return Scaffold (
52
+ appBar: AppBar (title: const Text ('Form Builder Example' )),
53
+ body: Padding (
54
+ padding: const EdgeInsets .all (10 ),
55
+ child: SingleChildScrollView (
56
+ child: Column (
57
+ children: < Widget > [
58
+ FormBuilder (
59
+ key: _formKey,
60
+ // enabled: false,
61
+ autovalidateMode: AutovalidateMode .disabled,
62
+ initialValue: const {
63
+ 'movie_rating' : 5 ,
64
+ 'best_language' : 'Dart' ,
65
+ 'age' : '13' ,
66
+ 'gender' : 'Male'
67
+ },
68
+ skipDisabled: true ,
69
+ child: Column (
70
+ children: < Widget > [
71
+ const SizedBox (height: 15 ),
72
+ FormBuilderDateTimePicker (
73
+ name: 'date' ,
74
+ initialEntryMode: DatePickerEntryMode .calendar,
75
+ initialValue: DateTime .now (),
76
+ inputType: InputType .both,
77
+ decoration: InputDecoration (
78
+ labelText: 'Appointment Time' ,
79
+ suffixIcon: IconButton (
80
+ icon: const Icon (Icons .close),
81
+ onPressed: () {
82
+ _formKey.currentState! .fields['date' ]
83
+ ? .didChange (null );
84
+ },
85
+ ),
86
+ ),
87
+ initialTime: const TimeOfDay (hour: 8 , minute: 0 ),
88
+ // locale: const Locale.fromSubtags(languageCode: 'fr'),
89
+ ),
90
+ FormBuilderDateRangePicker (
91
+ name: 'date_range' ,
92
+ firstDate: DateTime (1970 ),
93
+ lastDate: DateTime (2030 ),
94
+ format: DateFormat ('yyyy-MM-dd' ),
95
+ onChanged: _onChanged,
96
+ decoration: InputDecoration (
97
+ labelText: 'Date Range' ,
98
+ helperText: 'Helper text' ,
99
+ hintText: 'Hint text' ,
100
+ suffixIcon: IconButton (
101
+ icon: const Icon (Icons .close),
102
+ onPressed: () {
103
+ _formKey.currentState! .fields['date_range' ]
104
+ ? .didChange (null );
105
+ }),
106
+ ),
107
+ ),
108
+ FormBuilderSlider (
109
+ name: 'slider' ,
110
+ validator: FormBuilderValidators .compose ([
111
+ FormBuilderValidators .min (6 ),
112
+ ]),
113
+ onChanged: _onChanged,
114
+ min: 0.0 ,
115
+ max: 10.0 ,
116
+ initialValue: 7.0 ,
117
+ divisions: 20 ,
118
+ activeColor: Colors .red,
119
+ inactiveColor: Colors .pink[100 ],
120
+ decoration: const InputDecoration (
121
+ labelText: 'Number of things' ,
122
+ ),
123
+ ),
124
+ FormBuilderRangeSlider (
125
+ name: 'range_slider' ,
126
+ // validator: FormBuilderValidators.compose([FormBuilderValidators.min(context, 6)]),
127
+ onChanged: _onChanged,
128
+ min: 0.0 ,
129
+ max: 100.0 ,
130
+ initialValue: const RangeValues (4 , 7 ),
131
+ divisions: 20 ,
132
+ activeColor: Colors .red,
133
+ inactiveColor: Colors .pink[100 ],
134
+ decoration:
135
+ const InputDecoration (labelText: 'Price Range' ),
136
+ ),
137
+ FormBuilderCheckbox (
138
+ name: 'accept_terms' ,
139
+ initialValue: false ,
140
+ onChanged: _onChanged,
141
+ title: RichText (
142
+ text: const TextSpan (
143
+ children: [
144
+ TextSpan (
145
+ text: 'I have read and agree to the ' ,
146
+ style: TextStyle (color: Colors .black),
147
+ ),
148
+ TextSpan (
149
+ text: 'Terms and Conditions' ,
150
+ style: TextStyle (color: Colors .blue),
151
+ // Flutter doesn't allow a button inside a button
152
+ // https://github.com/flutter/flutter/issues/31437#issuecomment-492411086
153
+ /*
154
+ recognizer: TapGestureRecognizer()
155
+ ..onTap = () {
156
+ print('launch url');
157
+ },
158
+ */
159
+ ),
160
+ ],
161
+ ),
162
+ ),
163
+ validator: FormBuilderValidators .equal (
164
+ true ,
165
+ errorText:
166
+ 'You must accept terms and conditions to continue' ,
167
+ ),
168
+ ),
169
+ FormBuilderTextField (
170
+ autovalidateMode: AutovalidateMode .always,
171
+ name: 'age' ,
172
+ decoration: InputDecoration (
173
+ labelText: 'Age' ,
174
+ suffixIcon: _ageHasError
175
+ ? const Icon (Icons .error, color: Colors .red)
176
+ : const Icon (Icons .check, color: Colors .green),
177
+ ),
178
+ onChanged: (val) {
179
+ setState (() {
180
+ _ageHasError = ! (_formKey.currentState? .fields['age' ]
181
+ ? .validate () ??
182
+ false );
183
+ });
184
+ },
185
+ // valueTransformer: (text) => num.tryParse(text),
186
+ validator: FormBuilderValidators .compose ([
187
+ FormBuilderValidators .required (),
188
+ FormBuilderValidators .numeric (),
189
+ FormBuilderValidators .max (70 ),
190
+ ]),
191
+ // initialValue: '12',
192
+ keyboardType: TextInputType .number,
193
+ textInputAction: TextInputAction .next,
194
+ ),
195
+ FormBuilderDropdown <String >(
196
+ // autovalidate: true,
197
+ name: 'gender' ,
198
+ decoration: InputDecoration (
199
+ labelText: 'Gender' ,
200
+ suffix: _genderHasError
201
+ ? const Icon (Icons .error)
202
+ : const Icon (Icons .check),
203
+ ),
204
+ // initialValue: 'Male',
205
+ allowClear: true ,
206
+ hint: const Text ('Select Gender' ),
207
+ validator: FormBuilderValidators .compose (
208
+ [FormBuilderValidators .required ()]),
209
+ items: genderOptions
210
+ .map ((gender) => DropdownMenuItem (
211
+ alignment: AlignmentDirectional .center,
212
+ value: gender,
213
+ child: Text (gender),
214
+ ))
215
+ .toList (),
216
+ onChanged: (val) {
217
+ setState (() {
218
+ _genderHasError = ! (_formKey
219
+ .currentState? .fields['gender' ]
220
+ ? .validate () ??
221
+ false );
222
+ });
223
+ },
224
+ valueTransformer: (val) => val? .toString (),
225
+ ),
226
+ FormBuilderRadioGroup <String >(
227
+ decoration: const InputDecoration (
228
+ labelText: 'My chosen language' ,
229
+ ),
230
+ initialValue: null ,
231
+ name: 'best_language' ,
232
+ onChanged: _onChanged,
233
+ validator: FormBuilderValidators .compose (
234
+ [FormBuilderValidators .required ()]),
235
+ options:
236
+ ['Dart' , 'Kotlin' , 'Java' , 'Swift' , 'Objective-C' ]
237
+ .map ((lang) => FormBuilderFieldOption (
238
+ value: lang,
239
+ child: Text (lang),
240
+ ))
241
+ .toList (growable: false ),
242
+ controlAffinity: ControlAffinity .trailing,
243
+ ),
244
+ FormBuilderSegmentedControl (
245
+ decoration: const InputDecoration (
246
+ labelText: 'Movie Rating (Archer)' ,
247
+ ),
248
+ name: 'movie_rating' ,
249
+ // initialValue: 1,
250
+ // textStyle: TextStyle(fontWeight: FontWeight.bold),
251
+ options: List .generate (5 , (i) => i + 1 )
252
+ .map ((number) => FormBuilderFieldOption (
253
+ value: number,
254
+ child: Text (
255
+ number.toString (),
256
+ style: const TextStyle (
257
+ fontWeight: FontWeight .bold),
258
+ ),
259
+ ))
260
+ .toList (),
261
+ onChanged: _onChanged,
262
+ ),
263
+ FormBuilderSwitch (
264
+ title: const Text ('I Accept the terms and conditions' ),
265
+ name: 'accept_terms_switch' ,
266
+ initialValue: true ,
267
+ onChanged: _onChanged,
268
+ ),
269
+ FormBuilderCheckboxGroup <String >(
270
+ autovalidateMode: AutovalidateMode .onUserInteraction,
271
+ decoration: const InputDecoration (
272
+ labelText: 'The language of my people' ),
273
+ name: 'languages' ,
274
+ // initialValue: const ['Dart'],
275
+ options: const [
276
+ FormBuilderFieldOption (value: 'Dart' ),
277
+ FormBuilderFieldOption (value: 'Kotlin' ),
278
+ FormBuilderFieldOption (value: 'Java' ),
279
+ FormBuilderFieldOption (value: 'Swift' ),
280
+ FormBuilderFieldOption (value: 'Objective-C' ),
281
+ ],
282
+ onChanged: _onChanged,
283
+ separator: const VerticalDivider (
284
+ width: 10 ,
285
+ thickness: 5 ,
286
+ color: Colors .red,
287
+ ),
288
+ validator: FormBuilderValidators .compose ([
289
+ FormBuilderValidators .minLength (1 ),
290
+ FormBuilderValidators .maxLength (3 ),
291
+ ]),
292
+ ),
293
+ ],
294
+ ),
295
+ ),
296
+ Row (
297
+ children: < Widget > [
298
+ Expanded (
299
+ child: ElevatedButton (
300
+ onPressed: () {
301
+ if (_formKey.currentState? .saveAndValidate () ?? false ) {
302
+ debugPrint (_formKey.currentState? .value.toString ());
303
+ } else {
304
+ debugPrint (_formKey.currentState? .value.toString ());
305
+ debugPrint ('validation failed' );
306
+ }
307
+ },
308
+ child: const Text (
309
+ 'Submit' ,
310
+ style: TextStyle (color: Colors .white),
311
+ ),
312
+ ),
313
+ ),
314
+ const SizedBox (width: 20 ),
315
+ Expanded (
316
+ child: OutlinedButton (
317
+ onPressed: () {
318
+ _formKey.currentState? .reset ();
319
+ },
320
+ // color: Theme.of(context).colorScheme.secondary,
321
+ child: Text (
322
+ 'Reset' ,
323
+ style: TextStyle (
324
+ color: Theme .of (context).colorScheme.secondary),
325
+ ),
326
+ ),
327
+ ),
328
+ ],
329
+ ),
330
+ ],
331
+ ),
332
+ ),
333
+ ),
39
334
);
40
335
}
41
336
}
0 commit comments