375

I'd like to supply an initial value to a text field and redraw it with an empty value to clear the text. What's the best approach to do that with Flutter's APIs?

20 Answers 20

275

You can use a TextFormField instead of TextField, and use the initialValue property. for example

TextFormField(initialValue: "I am smart")
4
  • 6
    For some reason I couldn't use this with a dynamic object. Ended up needing the controller. Jan 19, 2019 at 17:11
  • 21
    This is only valid when a controller is not specified with a TextFormField. docs.flutter.io/flutter/material/TextFormField/… Mar 10, 2019 at 2:44
  • 4
    @AlexFallenstedt there is no need for this property when the controller is available Mar 10, 2019 at 9:03
  • 3
    I think this is risky because when rebuilding your widget tree your text can be replace with initial value. Dec 1, 2019 at 13:49
215

(From the mailing list. I didn't come up with this answer.)

class _FooState extends State<Foo> {
  TextEditingController _controller;

  @override
  void initState() {
    super.initState();
    _controller = new TextEditingController(text: 'Initial value');
  }

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
        new TextField(
          // The TextField is first built, the controller has some initial text,
          // which the TextField shows. As the user edits, the text property of
          // the controller is updated.
          controller: _controller,
        ),
        new RaisedButton(
          onPressed: () {
            // You can also use the controller to manipuate what is shown in the
            // text field. For example, the clear() method removes all the text
            // from the text field.
            _controller.clear();
          },
          child: new Text('CLEAR'),
        ),
      ],
    );
  }
}
4
  • I guess hint servers the same purpose. Jul 5, 2018 at 10:24
  • 9
    Just wonder which mailing list did you refer to in the answer? Oct 29, 2018 at 15:30
  • 2
    And how do we append / override textfield value into initial value? Feb 22, 2019 at 11:16
  • 5
    Also, be sure to dispose _controller on the widget's dispose. It is recommended by Google. It ensures that the resources are freed up when not needed.
    – amrit
    Sep 30, 2019 at 7:56
203

You don't have to define a separate variable in the widget scope, just do it inline:

TextField(
  controller: TextEditingController()..text = 'Your initial value',
  onChanged: (text) => {},
)
10
  • 3
    What is meant by the double dots in "TextEditingController()..text"?
    – Ray Li
    Aug 16, 2019 at 15:06
  • 25
    @RayLi It's called cascade operator. For info and example check here stackoverflow.com/questions/53136945/…
    – vovahost
    Aug 16, 2019 at 15:09
  • 4
    Thanks!. This perfect for dynamic creation of widgets from lists of objects :)
    – davaus
    Sep 17, 2019 at 4:16
  • 11
    @vovahost it's missing the dispose part, unfortunately. May 29, 2020 at 8:54
  • 4
    This might be bad because you should dispose of TextEditingController's in the widget's dispose() method. Jul 9, 2020 at 21:54
70

I've seen many ways of doing this on here. However I think this is a little more efficient or at least concise than the other answers.

TextField(
   controller: TextEditingController(text: "Initial Text here"),
)
3
  • 5
    The controller should be disposed! Nov 8, 2021 at 11:49
  • Michael the controller is automatically disposed when the view is unloaded
    – Kent
    Nov 9, 2021 at 15:45
  • 4
    @Kent Can you offer a reference for that statement about automatic disposal? Oct 18, 2022 at 19:02
48

If you are using TextEditingController then set the text to it, like below

TextEditingController _controller = new TextEditingController();


_controller.text = 'your initial text';

final your_text_name = TextFormField(
      autofocus: false,
      controller: _controller,
      decoration: InputDecoration(
        hintText: 'Hint Value',
      ),
    );

and if you are not using any TextEditingController then you can directly use initialValue like below

final last_name = TextFormField(
      autofocus: false,
      initialValue: 'your initial text',
      decoration: InputDecoration(
        hintText: 'Last Name',
      ),
    );

For more reference TextEditingController

1
  • I'm not sure if it's a good idea to set the initial value to the text property as per docs of TextEditingController.text property: Setting this will notify all the listeners of this TextEditingController that they need to update (it calls notifyListeners). For this reason, this value should only be set between frames, e.g. in response to user actions, not during the build, layout, or paint phases. (api.flutter.dev/flutter/widgets/TextEditingController/text.html) Aug 22, 2019 at 20:30
36

This can be achieved using TextEditingController.

To have an initial value you can add

TextEditingController _controller = TextEditingController(text: 'initial value');

or

If you are using TextFormField you have a initialValue property there. Which basically provides this initialValue to the widget automatically.

TextFormField(
  initialValue: 'initial value'
)

To clear the text you can use _controller.clear() method.

1
  • 5
    You cannot have controller and initialValue both non-null for TextFormField Jan 28, 2021 at 5:47
14

If you want to handle multiple TextInputs as asked by @MRT in the comment to the accepted answer, you can create a function that takes an initial value and returns a TextEditingController like this:

initialValue(val) {
  return TextEditingController(text: val);
}

Then, set this function as the controller for the TextInput and supply its initial value there like this:

controller: initialValue('Some initial value here....')

You can repeat this for the other TextInputs.

2
  • 1
    controller: searchFieldController..text = viewModel.searchKeyword.value, :)
    – om-ha
    Jan 28, 2022 at 9:09
  • Can be used with TextField too.
    – om-ha
    Jan 28, 2022 at 9:09
10
class _YourClassState extends State<YourClass> {
  TextEditingController _controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    _controller.text = 'Your message';
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: TextFormField(
        controller: _controller,
        decoration: InputDecoration(labelText: 'Send message...'),
      ),
    );
  }
}
8
TextEdittingController _controller = new TextEdittingController(text: "your Text");

or

@override
  void initState() {
    super.initState();
    _Controller.text = "Your Text";
    }
6

If you use TextEditingController just use the line in your class.

TextEditingController txtController = TextEditingController(text: 'Initial value')

TextField(
  controller: txtController,
);

If you don't use TextEditingController just go for initialValue

TextFormField(
      initialValue: 'your initial text',
  );

Full code

class _TestScreen extends State<Test> {
  TextEditingController _controller;

  @override
  void initState() {
    super.initState();
    _controller = new TextEditingController(text: 'Initial value');
  }

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
       TextFormField(       // First method
          initialValue: "Initial text"
        ),
       TextField(       // Second method
          controller: _controller, // Controller has the initial value
        ),
        
      ],
    );
  }
}
5

inside class,

  final usernameController = TextEditingController(text: 'bhanuka');

TextField,

   child: new TextField(
        controller: usernameController,
    ...
)
5

Easy and Efficient way

Assign controller to your TextFormField or TextField and in initState you can initialise it to the initial value like this

_controller = TextEditingController(text: 'Your initial value');
5

Since none of the answers mention it, the TextEditingController should be disposed off after use. As in:

class MyWidget extends StatefulWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  MyWidgetState createState() => MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {
  final myController = TextEditingController(text: "Initial value");

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: myController,
    );
  }

  @override
  void dispose() {
    // dispose it here
    myController.dispose();
    super.dispose();
  }
}
1
  • How would one match the InputDecoration?
    – user11720628
    Feb 20, 2022 at 14:25
3
  1. When you are Using TextEditingController

If you use TextEditingController, set its text field to the desired value

TextEditingController txtController = TextEditingController()..text = 'Your initial text value'; 
TextField( controller: txtController ..... ) 
  1. When you are Not Using TextEditingController

If you are not using the TextEditingContller, use the initialValue field directly from the TextField widget:

TextFormField( initialValue: "Your initial text value" )
3

if you use text form field and pass data from previous page to next page text form field use this

class ProfilePage extends StatefulWidget {

  late final String fname;

    ProfilePage({required this.fname});

  @override
  State<ProfilePage> createState() => _ProfilePageState();
}

class _ProfilePageState extends State<ProfilePage> {
  final _form = GlobalKey<FormState>();
  
  late var FullNameController = TextEditingController(text: widget.fname);
  
}
2
  • What the late is for here?
    – Wiktor
    Sep 3, 2022 at 10:01
  • 1
    This is just what I was looking for, where I passed a string between pages. @Wiktor the late modifier allows the field to be initialized later, after its declaration. In this case, it avoids the error The instance member 'widget' can't be accessed in an initializer.
    – penguinrob
    Nov 30, 2022 at 3:42
2

As for the above-mentioned answers all are right, but one thing is missing that I wanna add to it is how to customize the style of this default text of TextFormField.

TextEditingController textController = TextEditingController(text: '4');

 TextFormField(
    controller: textController,
     // This style property will customize the default controller text
    style: TextStyle(
    color: Colors.white,
    fontSize: 18,
    fontWeight: FontWeight.bold,
   ),
    ),

For this scenario, I would prefer to use TextEditingController instead of initialValue, Because if you want to change it later or modify it, then textController will continuously listen for your TextFormField input changes. This is my personal view, let me know if I am wrong.

2

you can use this code sample:

    TextFormField(
          controller: nameController?..text='Your initial value',
         
        ),
1

You can do all of the above things but, if you want the API to show your data when its's get loaded it shows up like profile page. so here's the code:

TextEditingController _nameController = TextEditingController(); // initialize the controller
 // when API gets the data, do this:
 _nameController.text = response.data.fullName; or _nameController.text = "Apoorv Pandey"

I hope it clears everything. Happy coding!

6
  • This works for me but can we do it with focus node or using _initValue also?
    – Rohan
    Aug 2, 2021 at 5:33
  • I can't understand your question, sorry can you elaborate a bit more? Aug 2, 2021 at 6:04
  • yes like i am using focus node and _initvalue={ name: ''} in a name formtextfield and I want my _initvalue['name'] to be prefilled by fetching the name from server so after using controller I got the name but I am asking can we do without controller also ?
    – Rohan
    Aug 2, 2021 at 6:24
  • As my experience you can't do that without controller, but you can use a variable of String type and pass in the label text inside decoration of the text form field it will be prefilled, and when user click on it it will go up and will be empty Aug 2, 2021 at 6:47
  • 1
    ok thanks earlier I was trying with initialValue and it didn't work out but I would go with the controller for the time being
    – Rohan
    Aug 2, 2021 at 10:27
1
final TextEditingController _textFieldController = TextEditingController();
@override
void initState() {
  _textFieldController.text = "Hello";
  super.initState();
}
1
  • 1
    Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation? Sep 23, 2023 at 1:24
0

The best way would be replacing TextField to TextFormField because, we can use the property initialValue and avoid the complexity to manage state.

Using TextEditingControlleris not optimal because it needs to recreate a instance of TextEditingController just to pass a initial value. Additionally, how can you handle if you need to customize more and require access the text controller in other places ? It would be so confused

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.