Being able to work with a form field, to get values, know when it has been updated, etc, are important aspects for any form work.
In this example we’re going to look at detecting when a TextFormField changes and getting those values.
We are going to use the previous example of Form Fields in Flutter.
Using a callback method
Let’s start with something simple, like a callback method. This form of event handler is when the text is going to change. So it will be onChanged()
.
TextFormField (
onChanged: (text) {
print('First text field: $text');
},
),
Here you can see that we’ve added the onChanged property, and text
is being passed into that function. Text is going to be the new value of the TextFormField.
In this case, we are simply taking the changed text, and printing it to the console window. If you save and do a hot reload, then type something in, you will see that each time you type a letter, you will see it appear in the console window.
Use a TextEditingController
Another way of doing this is to use a TextEditingController object as a controller property. This is more powerful in what you can do, but it requires a more elaborate setup.
The first thing we’ll do is remove the onChanged callback method from the previous step as we’re not using that.
The next thing we need to do, is setup the controller. This will go before the build method. I put it after the GlobalKey from the last project.
class MyFormState extends State<MyForm> {
// The global key that uniquely identifies the Form widget
// and allows validation of the form.
final _formKey = GlobalKey<FormState>();
final myController = TextEditingController();
@override
Widget build(BuildContext context) {
/* ... */
}
Applying the Controller
Next we’ll need to attach the controller, myController, to the TextFormField.
TextFormField(
controller: myController,
),
And then add a new function to print when the text is changed.
void _printUpdatedValue() {
print('Second text field: ${myController.text}');
}
This function will need to go in the widget. I put it after the dispose method.
Initializing the Event Listener
Now we need it apply the event listener. As with a previous example, we will do that within the initState method.
@override
void initState() {
super.initState();
// Start listening to changes.
myController.addListener(_printUpdatedValue);
}
Updating Dispose
Next we will need to add/override the dispose method. I put this right before my build method. This will cancel the event listener since it won’t be needed if the form screen goes away.
@override
void dispose() {
// Clean up the controller when the widget is removed from the widget tree.
myController.dispose();
super.dispose();
}
As with previous dispose methods we’ve looked at, we dispose of the myControler first, before calling super.dispose(), which runs the normal dispose process.
Testing the Event Handler
Now that the controller has been applied and the event listener has been set up (and disposed of when appropriate because we always want to stop what we start/close what we open), we can save and test.
This allows us to see the results of our work, and you will see the text entered being put into our console window.
Modifying the Text of a Form Field
Being able to retrieve the text is good, but what if we need to make a change to the value, duplicating a form field for example. Well, starting where we are, makes this easy.
First we’re going to create a second controller object. For simplicity I called this myController2.
final myController2 = TextEditingController();
Then we will add a new TextFormField to our Widget. I put my right under the existing text field, but before the elevated button.
Padding(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 16),
child: TextFormField(
controller: myController2,
decoration: const InputDecoration(
border: UnderlineInputBorder(), labelText: 'Duplicated text'),
),
),
Notice that I also wrapped a Padding object around it to make it easier to read, and gave it some label text. I removed the validator code as it was not necessary here in this example.
Very importantly, I changed the controller to myController2.
I added the new controller to the dispose method, to make sure it got properly cleaned up.
Updating the _printUpdatedValue
Finally we need to update the _printUpdatedValue
method.
This method has been copying data to the console window, but we want to see it somewhere else, the second text box.
Luckily using the controller object, makes this easy, as we can get the text value of the controller, and thus the TextFormField. Plus, that attribute is both read and write, so it makes it even easier.
We will keep the existing code, so it will still write to the console, but now also duplicated it in our secondary text field.
void _printUpdatedValue() {
// write text value to the console window
print('Text field: ${myController.text}');
// write the first text field value to the second text field
myController2.text = myController.text;
}
Handling Changes and Values of a Text Field in Flutter was originally found on Access 2 Learn
One Comment
Comments are closed.