Reputation: 1141
I am trying to solve form validation in my app. Every time I click to TextFromField, the focus is lost and keyboard hide. I found that problem is with "_formKey". But I need it to validation. How to solve it?
code snippet:
class _TodoCreateDetailPageState extends State<TodoPage> {
@override
Widget build(BuildContext context) {
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
String _title = widget.todo == null ? "New TODO" : widget.todo.title;
String _message;
return new Scaffold(
appBar: new AppBar(
title: new Text(_title),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.save), onPressed: null),
body: new Padding(
padding: new EdgeInsets.all(20.0),
child: new Form(
key: _formKey,
child: new Column(
children: <Widget>[
new TextField(
decoration: new InputDecoration(labelText: 'Title'),
onChanged: (String value) {
_title = value;
},
),
new TextField(
decoration: new InputDecoration(labelText: 'Message'),
onChanged: (String value) {
_message = value;
},
)
],
))),
);
}
Upvotes: 14
Views: 15694
Reputation: 17576
I think there's a much simpler solution that hasn't been mentioned yet and it has to do with the difference between GlobalKey and GlobalObjectKey.
A GlobalKey is only equal to itself and so each time your stateless widget is rebuilt, a new GlobalKey is created and the form is reset.
A GlobalObjectKey on the other hand is equal to any other GlobalObjectKey that has the same object:
GlobalObjectKey key1 = GlobalObjectKey('test');
GlobalObjectKey key2 = GlobalObjectKey('test');
key1 == key2; // True
So in this case, you should initialize your formKey as a GlobalObjectKey like this:
GlobalObjectKey<FormState> formKey = const GlobalObjectKey<FormState>('form');
Upvotes: 5
Reputation: 353
this issue is due to GlobalKey Initialization with in build()
@override
Widget build(BuildContext context){
//here is the reason of losing focus.
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>()
}
Remove it from build and you are all good.
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
//this will work fine when you move key outside the build();
@override
Widget build(BuildContext context){
}
Upvotes: 12
Reputation: 21
I had the same problem, and found a solution for that, just define a controller variable outside the build method. Use TextEditingController()
Upvotes: 2
Reputation: 3070
You seem to know that the problem is in the key itself, as in #6783. The solution is to avoid constructing your validation key every time. So, you may do it like this (or even make it a widget's property):
class _TodoCreateDetailPageState extends State<TodoPage> {
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
String _title = widget.todo == null ? "New TODO" : widget.todo.title;
String _message;
return new Scaffold(
appBar: new AppBar(
title: new Text(_title),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.save), onPressed: null),
body: new Padding(
padding: new EdgeInsets.all(20.0),
child: new Form(
key: _formKey,
child: new Column(
children: <Widget>[
new TextField(
decoration: new InputDecoration(labelText: 'Title'),
onChanged: (String value) {
_title = value;
},
),
new TextField(
decoration: new InputDecoration(labelText: 'Message'),
onChanged: (String value) {
_message = value;
},
)
],
))),
);
}
Upvotes: 5
Reputation: 119
Change StatelessWidget
to StatefulWidget
works for me, as Derek Lakin said in comments.
Upvotes: 10