Stepan
Stepan

Reputation: 1141

TextFormField is losing focus - flutter

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

Answers (5)

Code on the Rocks
Code on the Rocks

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

Muhammad Qamar Iqbal
Muhammad Qamar Iqbal

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

Anmol Mishra
Anmol Mishra

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

Smily
Smily

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

Will
Will

Reputation: 119

Change StatelessWidget to StatefulWidget works for me, as Derek Lakin said in comments.

Upvotes: 10

Related Questions