Garrett
Garrett

Reputation: 1792

Flutter TextField with controller not updating the field at all

I thought I had this right, but evidently something is off. Simple text field with the default text set by the controller to newUser['firstName']. newUser is of type Map<String, Dynamic>

TextField(
    decoration: InputDecoration(labelText: 'First Name'),
    controller: TextEditingController(text: newUser['firstName']), // currently set to "Garrett"
    onChanged: (text) {
        print('TEXT: $text'); // only gives the current value plus the last letter hit, ex. 
        "Garrettr", "Garrettf", etc.

        setState(() {
            newUser['firstName'] = text;
        });

        print('FIRST NAME: ${newUser['firstName']}'); // same as text
    },
),

No errors, but when I type in the field to change the text nothing happens and the newUser['firstName'] will equal "Garrette" or "Garrettr", etc.. As you can see in the code the text that comes through onChanged doesn't seem to be right, not sure what I'm doing wrong though.

Upvotes: 2

Views: 3435

Answers (2)

danypata
danypata

Reputation: 10175

The easiest way for you, since you have a lot of fields is to create a "descriptor class" for your fields. Something like this.

class InputFieldDescriptor {
  final String key;
  final String placeholder;
  final TextEditingController controller;

  InputFieldDescriptor(this.key, this.placeholder, this.controller);
}

class WidgetThatDisplayFields extends StatefulWidget {
  @override
  _WidgetThatDisplayFields createState() => _WidgetThatDisplayFields();
}

class _WidgetThatDisplayFields extends State<WidgetThatDisplayFields> {
  List<InputFieldDescriptor> _descriptors = [
    InputFieldDescriptor("user_name", "User name", TextEditingController()),
    InputFieldDescriptor("email", "Email", TextEditingController()),
    InputFieldDescriptor("password", "password", TextEditingController()),
  ];

  List<Widget> _inputFields() {
    return _descriptors.map((descriptor) {
      return TextField(
          decoration: InputDecoration(labelText: descriptor.placeholder),
          controller: descriptor.controller); // currently set to "Garrett"
    }).toList();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: _inputFields(),
    );
  }

  Map<String, String> _collect() {
    Map<String, String> data = {};
    _descriptors.forEach((descriptor) {
      data[descriptor.key] = descriptor.controller.text;
    });
    return data;
  }
}

Upvotes: 2

Khalil
Khalil

Reputation: 557

Up on your code before the TextField do initialize something like final TextEditingController anyThing = new TextEditingController();

Now to get the new text set newUser['firstName'] = anyThing.text

Try this and let me know if you need further help.

So the whole thing would be:

final TextEditingController anyThing = new TextEditingController();
TextField(
        decoration: InputDecoration(labelText: 'First Name'),
        controller: anyThing, // currently set to "Garrett"
        onChanged: (text) {
          print('TEXT: $text'); // only gives the current value plus the last letter hit, ex.

          setState(() {
          newUser['firstName'] = text;
          });

          print('FIRST NAME: ${newUser['firstName']}'); // same as text
        },
      ),

Upvotes: 1

Related Questions