Skip to content

Commit 7cf7e1d

Browse files
committed
feat(core): include the whole example in lib/main.dart to show on pub.dev. Fixes #1017
1 parent b30c48b commit 7cf7e1d

File tree

2 files changed

+323
-26
lines changed

2 files changed

+323
-26
lines changed
Lines changed: 314 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_form_builder/flutter_form_builder.dart';
23
import 'package:flutter_localizations/flutter_localizations.dart';
34
import 'package:form_builder_validators/form_builder_validators.dart';
4-
5-
import 'home_page.dart';
5+
import 'package:intl/intl.dart';
66

77
void main() => runApp(const MyApp());
88

@@ -14,28 +14,323 @@ class MyApp extends StatelessWidget {
1414
return MaterialApp(
1515
title: 'Flutter FormBuilder Demo',
1616
debugShowCheckedModeBanner: false,
17-
theme: ThemeData(
18-
primarySwatch: Colors.blue,
19-
inputDecorationTheme: const InputDecorationTheme(
20-
labelStyle: TextStyle(color: Colors.blueAccent),
21-
),
22-
),
2317
localizationsDelegates: const [
2418
FormBuilderLocalizations.delegate,
2519
GlobalMaterialLocalizations.delegate,
2620
GlobalWidgetsLocalizations.delegate,
2721
],
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+
),
39334
);
40335
}
41336
}

packages/flutter_form_builder/example/lib/sources/complete_form.dart

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,21 @@ class CompleteFormState extends State<CompleteForm> {
4747
const SizedBox(height: 15),
4848
FormBuilderDateTimePicker(
4949
name: 'date',
50+
initialEntryMode: DatePickerEntryMode.calendar,
5051
initialValue: DateTime.now(),
51-
inputType: InputType.time,
52+
inputType: InputType.both,
5253
decoration: InputDecoration(
5354
labelText: 'Appointment Time',
5455
suffixIcon: IconButton(
55-
icon: const Icon(Icons.close),
56-
onPressed: () {
57-
_formKey.currentState!.fields['date']
58-
?.didChange(null);
59-
}),
56+
icon: const Icon(Icons.close),
57+
onPressed: () {
58+
_formKey.currentState!.fields['date']
59+
?.didChange(null);
60+
},
61+
),
6062
),
6163
initialTime: const TimeOfDay(hour: 8, minute: 0),
62-
locale: const Locale.fromSubtags(languageCode: 'fr'),
64+
// locale: const Locale.fromSubtags(languageCode: 'fr'),
6365
),
6466
FormBuilderDateRangePicker(
6567
name: 'date_range',

0 commit comments

Comments
 (0)