To validate the whole Form
in flutter, a GloabalKey<FormState>
must be provided. It looks fine when buttons for interaction with the form contained inside of form, but when, for example, form is a child of AlertDialog
, the key has to be passed from the dialog widget, and it doesn't look good. Is there any better solution for obtaining FormState
from a parent widget?
Here's the example:
main
void main() {
runApp(
const MaterialApp(
home: InitialScreen(),
),
);
}
Initial Screen
class InitialScreen extends StatelessWidget {
const InitialScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return FormDialog();
},
);
},
),
);
}
}
Form Dialog
class FormDialog extends StatelessWidget {
FormDialog({super.key});
GlobalKey<FormState> myFormState = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Create new item'),
content: MyForm(
formCurrentState: myFormState,
),
actions: <Widget>[
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('Add'),
onPressed: () {
if (myFormState.currentState!.validate()) {
print("All fine");
Navigator.of(context).pop();
} else {
print("Error");
}
},
),
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
}
}
My Form
class MyForm extends StatefulWidget {
const MyForm({super.key, required this.formCurrentState});
final GlobalKey<FormState> formCurrentState;
@override
State<MyForm> createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
GlobalKey<FormState>? formCurrentState;
@override
void initState() {
super.initState();
formCurrentState = widget.formCurrentState;
}
@override
Widget build(BuildContext context) {
return Form(
key: formCurrentState,
child: TextFormField(
validator: (value) {
if (value == "") {
return "Please, enter some text";
} else {
return null;
}
},
),
);
}
}