Skip to content

Commit 6b7953e

Browse files
feat: add dynamic fields example
1 parent e9633af commit 6b7953e

File tree

3 files changed

+153
-1
lines changed

3 files changed

+153
-1
lines changed

example/lib/main.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:example/sources/dynamic_fields.dart';
12
import 'package:flutter/material.dart';
23
import 'package:flutter_localizations/flutter_localizations.dart';
34
import 'package:form_builder_validators/form_builder_validators.dart';
@@ -88,6 +89,22 @@ class _HomePage extends StatelessWidget {
8889
},
8990
),
9091
const Divider(),
92+
ListTile(
93+
title: const Text('Dynamic Form'),
94+
trailing: const Icon(Icons.arrow_right_sharp),
95+
onTap: () {
96+
Navigator.of(context).push(
97+
MaterialPageRoute(
98+
builder: (context) {
99+
return const CodePage(
100+
title: 'Dynamic Form',
101+
child: DynamicFields(),
102+
);
103+
},
104+
),
105+
);
106+
},
107+
),
91108
],
92109
),
93110
);

example/lib/sources/custom_fields.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ class CustomFields extends StatefulWidget {
1111

1212
class _CustomFieldsState extends State<CustomFields> {
1313
final _formKey = GlobalKey<FormBuilderState>();
14-
var options = ["Option 1", "Option 2", "Option 3"];
1514

1615
@override
1716
Widget build(BuildContext context) {
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_form_builder/flutter_form_builder.dart';
3+
import 'package:form_builder_validators/form_builder_validators.dart';
4+
5+
class DynamicFields extends StatefulWidget {
6+
const DynamicFields({Key? key}) : super(key: key);
7+
8+
@override
9+
State<DynamicFields> createState() => _DynamicFieldsState();
10+
}
11+
12+
class _DynamicFieldsState extends State<DynamicFields> {
13+
final _formKey = GlobalKey<FormBuilderState>();
14+
final List<Widget> fields = [];
15+
String savedValue = '';
16+
17+
@override
18+
void initState() {
19+
savedValue = _formKey.currentState?.value.toString() ?? '';
20+
super.initState();
21+
}
22+
23+
@override
24+
Widget build(BuildContext context) {
25+
return FormBuilder(
26+
key: _formKey,
27+
clearValueOnUnregister: true,
28+
child: Column(
29+
children: <Widget>[
30+
const SizedBox(height: 20),
31+
FormBuilderTextField(
32+
name: 'name',
33+
validator: FormBuilderValidators.required(),
34+
decoration: const InputDecoration(
35+
label: Text('Started field'),
36+
),
37+
),
38+
...fields,
39+
const SizedBox(height: 10),
40+
Row(
41+
children: <Widget>[
42+
Expanded(
43+
child: MaterialButton(
44+
color: Theme.of(context).colorScheme.secondary,
45+
child: const Text(
46+
"Submit",
47+
style: TextStyle(color: Colors.white),
48+
),
49+
onPressed: () {
50+
_formKey.currentState!.saveAndValidate();
51+
setState(() {
52+
savedValue =
53+
_formKey.currentState?.value.toString() ?? '';
54+
});
55+
},
56+
),
57+
),
58+
const SizedBox(width: 20),
59+
Expanded(
60+
child: MaterialButton(
61+
color: Theme.of(context).colorScheme.secondary,
62+
child: const Text(
63+
"Add field",
64+
style: TextStyle(color: Colors.white),
65+
),
66+
onPressed: () {
67+
setState(() {
68+
fields.add(NewTextField(
69+
name: 'name_${fields.length}',
70+
onDelete: () {
71+
setState(() {
72+
fields.removeAt(fields.length - 1);
73+
});
74+
},
75+
));
76+
});
77+
},
78+
),
79+
),
80+
],
81+
),
82+
const Divider(height: 40),
83+
Text('Saved value: ${_formKey.currentState?.value.toString() ?? ''}'),
84+
],
85+
),
86+
);
87+
}
88+
}
89+
90+
class NewTextField extends StatefulWidget {
91+
const NewTextField({
92+
super.key,
93+
required this.name,
94+
this.onDelete,
95+
this.unregisterField,
96+
});
97+
final String name;
98+
final VoidCallback? onDelete;
99+
final void Function(String name, FormBuilderFieldState field)?
100+
unregisterField;
101+
102+
@override
103+
State<NewTextField> createState() => _NewTextFieldState();
104+
}
105+
106+
class _NewTextFieldState extends State<NewTextField> {
107+
@override
108+
void dispose() {
109+
super.dispose();
110+
// widget.unregisterField?.call(widget.name, this);
111+
}
112+
113+
@override
114+
Widget build(BuildContext context) {
115+
return Padding(
116+
padding: const EdgeInsets.only(bottom: 8),
117+
child: Row(
118+
children: [
119+
Expanded(
120+
child: FormBuilderTextField(
121+
name: widget.name,
122+
validator: FormBuilderValidators.minLength(4),
123+
decoration: const InputDecoration(
124+
label: Text('New field'),
125+
),
126+
),
127+
),
128+
IconButton(
129+
icon: const Icon(Icons.delete_forever),
130+
onPressed: widget.onDelete,
131+
),
132+
],
133+
),
134+
);
135+
}
136+
}

0 commit comments

Comments
 (0)