In Flutter, we can achieve text field validation by using TextEditingController
class. TextEditingController
in a text field can gain control over the input text and implement various validation techniques. It is a valuable tool for ensuring data integrity, handling user input errors, and creating interactive forms in Flutter applications.
We can follow the instructions given below to implement validation in the text field using TextEditingController
Firstly, we can create a StatefulWidget
subclass that will contain both TextField
and ElevatedButton
class ValidationExample extends StatefulWidget {
const ValidationExample({Key key, this.onSubmit}) : super(key: key);
final ValueChanged<String> onSubmit;
@override
State<ValidationExample> createState() => _ValidationExampleState();
}
class _ValidationExampleState extends State<ValidationExample> {
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
decoration: InputDecoration(
labelText: 'Enter your Name',
// TODO: add errorHint
),
),
ElevatedButton(
// TODO: implement callback
onPressed: () {},
style: ButtonStyle(
backgroundColor:MaterialStateProperty.all(Colors.red),
),
child: Text(
'Submit',
style: Theme.of(context).textTheme.headline6,
),
)
],
);
}
}
If we run the above code in a Flutter project, we will get the following output with a simple TextField
and ElevatedButton
without any validation.
TextEditingController
We can create a variable of TextEditingController
class by adding the following lines in the state subclass:
class _ValidationExampleState extends State<ValidationExample> {
// create a TextEditingController
final _controller = TextEditingController();
// dispose it when the widget is unmounted
@override
void dispose() {
_controller.dispose();
super.dispose();
}
...
}
After creating a TextEditingController
variable, we can add it to the TextField
just by adding the following lines.
TextField(
// use this to control the text field
controller: _controller,
decoration: InputDecoration(
labelText: 'Enter your Name',
),
),
We can define a getter variable _errorText
where we will define all the logic for validation.
String get _errorText {
// at any time, we can get the text from _controller.value.text
final text = _controller.value.text;
// Note: you can do your own custom validation here
// Move this logic this outside the widget for more testable code
if (text.isEmpty) {
return 'Name can\'t be empty';
}
if (text.length < 3) {
return 'Name is too short. Minimum 3 characters required.';
}
// return null if the text is valid
return null;
}
Now we can pass it on to the TextField
.
After placing _errorText()
we can apply some logic to onPressed
the callback function of the elevated button.
onPressed: _controller.value.text.isNotEmpty
? _submit
: null,
To apply the above logic, we have to define the _submit()
function as well.
void _submit() {
// if there is no error text
if (_errorText == null) {
// notify the parent widget via the onSubmit callback
widget.onSubmit(_controller.value.text);
}
}
Now, we have to rebuild the whole widget tree to reflect the changes whenever the text changes in the text field by adding the following line in the TextField widget.
onChanged: (_) => setState(() {}),
We get the following output by putting together the code explained above.
bmFtZTogbmV3YXBwCmRlc2NyaXB0aW9uOiBBIG5ldyBGbHV0dGVyIHByb2plY3QuCiMgVGhlIGZvbGxvd2luZyBsaW5lIHByZXZlbnRzIHRoZSBwYWNrYWdlIGZyb20gYmVpbmcgYWNjaWRlbnRhbGx5IHB1Ymxpc2hlZCB0bwojIHB1Yi5kZXYgdXNpbmcgYGZsdXR0ZXIgcHViIHB1Ymxpc2hgLiBUaGlzIGlzIHByZWZlcnJlZCBmb3IgcHJpdmF0ZSBwYWNrYWdlcy4KcHVibGlzaF90bzogJ25vbmUnICMgUmVtb3ZlIHRoaXMgbGluZSBpZiB5b3Ugd2lzaCB0byBwdWJsaXNoIHRvIHB1Yi5kZXYKCiMgVGhlIGZvbGxvd2luZyBkZWZpbmVzIHRoZSB2ZXJzaW9uIGFuZCBidWlsZCBudW1iZXIgZm9yIHlvdXIgYXBwbGljYXRpb24uCiMgQSB2ZXJzaW9uIG51bWJlciBpcyB0aHJlZSBudW1iZXJzIHNlcGFyYXRlZCBieSBkb3RzLCBsaWtlIDEuMi40MwojIGZvbGxvd2VkIGJ5IGFuIG9wdGlvbmFsIGJ1aWxkIG51bWJlciBzZXBhcmF0ZWQgYnkgYSArLgojIEJvdGggdGhlIHZlcnNpb24gYW5kIHRoZSBidWlsZGVyIG51bWJlciBtYXkgYmUgb3ZlcnJpZGRlbiBpbiBmbHV0dGVyCiMgYnVpbGQgYnkgc3BlY2lmeWluZyAtLWJ1aWxkLW5hbWUgYW5kIC0tYnVpbGQtbnVtYmVyLCByZXNwZWN0aXZlbHkuCiMgSW4gQW5kcm9pZCwgYnVpbGQtbmFtZSBpcyB1c2VkIGFzIHZlcnNpb25OYW1lIHdoaWxlIGJ1aWxkLW51bWJlciB1c2VkIGFzIHZlcnNpb25Db2RlLgojIFJlYWQgbW9yZSBhYm91dCBBbmRyb2lkIHZlcnNpb25pbmcgYXQgaHR0cHM6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20vc3R1ZGlvL3B1Ymxpc2gvdmVyc2lvbmluZwojIEluIGlPUywgYnVpbGQtbmFtZSBpcyB1c2VkIGFzIENGQnVuZGxlU2hvcnRWZXJzaW9uU3RyaW5nIHdoaWxlIGJ1aWxkLW51bWJlciBpcyB1c2VkIGFzIENGQnVuZGxlVmVyc2lvbi4KIyBSZWFkIG1vcmUgYWJvdXQgaU9TIHZlcnNpb25pbmcgYXQKIyBodHRwczovL2RldmVsb3Blci5hcHBsZS5jb20vbGlicmFyeS9hcmNoaXZlL2RvY3VtZW50YXRpb24vR2VuZXJhbC9SZWZlcmVuY2UvSW5mb1BsaXN0S2V5UmVmZXJlbmNlL0FydGljbGVzL0NvcmVGb3VuZGF0aW9uS2V5cy5odG1sCiMgSW4gV2luZG93cywgYnVpbGQtbmFtZSBpcyB1c2VkIGFzIHRoZSBtYWpvciwgbWlub3IsIGFuZCBwYXRjaCBwYXJ0cwojIG9mIHRoZSBwcm9kdWN0IGFuZCBmaWxlIHZlcnNpb25zIHdoaWxlIGJ1aWxkLW51bWJlciBpcyB1c2VkIGFzIHRoZSBidWlsZCBzdWZmaXguCnZlcnNpb246IDEuMC4wKzEKCmVudmlyb25tZW50OgogIHNkazogJz49My4wLjUgPDQuMC4wJwoKIyBEZXBlbmRlbmNpZXMgc3BlY2lmeSBvdGhlciBwYWNrYWdlcyB0aGF0IHlvdXIgcGFja2FnZSBuZWVkcyBpbiBvcmRlciB0byB3b3JrLgojIFRvIGF1dG9tYXRpY2FsbHkgdXBncmFkZSB5b3VyIHBhY2thZ2UgZGVwZW5kZW5jaWVzIHRvIHRoZSBsYXRlc3QgdmVyc2lvbnMKIyBjb25zaWRlciBydW5uaW5nIGBmbHV0dGVyIHB1YiB1cGdyYWRlIC0tbWFqb3ItdmVyc2lvbnNgLiBBbHRlcm5hdGl2ZWx5LAojIGRlcGVuZGVuY2llcyBjYW4gYmUgbWFudWFsbHkgdXBkYXRlZCBieSBjaGFuZ2luZyB0aGUgdmVyc2lvbiBudW1iZXJzIGJlbG93IHRvCiMgdGhlIGxhdGVzdCB2ZXJzaW9uIGF2YWlsYWJsZSBvbiBwdWIuZGV2LiBUbyBzZWUgd2hpY2ggZGVwZW5kZW5jaWVzIGhhdmUgbmV3ZXIKIyB2ZXJzaW9ucyBhdmFpbGFibGUsIHJ1biBgZmx1dHRlciBwdWIgb3V0ZGF0ZWRgLgpkZXBlbmRlbmNpZXM6CiAgZmx1dHRlcjoKICAgIHNkazogZmx1dHRlcgoKCiAgIyBUaGUgZm9sbG93aW5nIGFkZHMgdGhlIEN1cGVydGlubyBJY29ucyBmb250IHRvIHlvdXIgYXBwbGljYXRpb24uCiAgIyBVc2Ugd2l0aCB0aGUgQ3VwZXJ0aW5vSWNvbnMgY2xhc3MgZm9yIGlPUyBzdHlsZSBpY29ucy4KICBjdXBlcnRpbm9faWNvbnM6IF4xLjAuMgoKZGV2X2RlcGVuZGVuY2llczoKICBmbHV0dGVyX3Rlc3Q6CiAgICBzZGs6IGZsdXR0ZXIKCiAgIyBUaGUgImZsdXR0ZXJfbGludHMiIHBhY2thZ2UgYmVsb3cgY29udGFpbnMgYSBzZXQgb2YgcmVjb21tZW5kZWQgbGludHMgdG8KICAjIGVuY291cmFnZSBnb29kIGNvZGluZyBwcmFjdGljZXMuIFRoZSBsaW50IHNldCBwcm92aWRlZCBieSB0aGUgcGFja2FnZSBpcwogICMgYWN0aXZhdGVkIGluIHRoZSBgYW5hbHlzaXNfb3B0aW9ucy55YW1sYCBmaWxlIGxvY2F0ZWQgYXQgdGhlIHJvb3Qgb2YgeW91cgogICMgcGFja2FnZS4gU2VlIHRoYXQgZmlsZSBmb3IgaW5mb3JtYXRpb24gYWJvdXQgZGVhY3RpdmF0aW5nIHNwZWNpZmljIGxpbnQKICAjIHJ1bGVzIGFuZCBhY3RpdmF0aW5nIGFkZGl0aW9uYWwgb25lcy4KICBmbHV0dGVyX2xpbnRzOiBeMi4wLjAKCiMgRm9yIGluZm9ybWF0aW9uIG9uIHRoZSBnZW5lcmljIERhcnQgcGFydCBvZiB0aGlzIGZpbGUsIHNlZSB0aGUKIyBmb2xsb3dpbmcgcGFnZTogaHR0cHM6Ly9kYXJ0LmRldi90b29scy9wdWIvcHVic3BlYwoKIyBUaGUgZm9sbG93aW5nIHNlY3Rpb24gaXMgc3BlY2lmaWMgdG8gRmx1dHRlciBwYWNrYWdlcy4KZmx1dHRlcjoKCiAgIyBUaGUgZm9sbG93aW5nIGxpbmUgZW5zdXJlcyB0aGF0IHRoZSBNYXRlcmlhbCBJY29ucyBmb250IGlzCiAgIyBpbmNsdWRlZCB3aXRoIHlvdXIgYXBwbGljYXRpb24sIHNvIHRoYXQgeW91IGNhbiB1c2UgdGhlIGljb25zIGluCiAgIyB0aGUgbWF0ZXJpYWwgSWNvbnMgY2xhc3MuCiAgdXNlcy1tYXRlcmlhbC1kZXNpZ246IHRydWUKCiAgIyBUbyBhZGQgYXNzZXRzIHRvIHlvdXIgYXBwbGljYXRpb24sIGFkZCBhbiBhc3NldHMgc2VjdGlvbiwgbGlrZSB0aGlzOgogICMgYXNzZXRzOgogICMgICAtIGltYWdlcy9hX2RvdF9idXJyLmpwZWcKICAjICAgLSBpbWFnZXMvYV9kb3RfaGFtLmpwZWcKCiAgIyBBbiBpbWFnZSBhc3NldCBjYW4gcmVmZXIgdG8gb25lIG9yIG1vcmUgcmVzb2x1dGlvbi1zcGVjaWZpYyAidmFyaWFudHMiLCBzZWUKICAjIGh0dHBzOi8vZmx1dHRlci5kZXYvYXNzZXRzLWFuZC1pbWFnZXMvI3Jlc29sdXRpb24tYXdhcmUKCiAgIyBGb3IgZGV0YWlscyByZWdhcmRpbmcgYWRkaW5nIGFzc2V0cyBmcm9tIHBhY2thZ2UgZGVwZW5kZW5jaWVzLCBzZWUKICAjIGh0dHBzOi8vZmx1dHRlci5kZXYvYXNzZXRzLWFuZC1pbWFnZXMvI2Zyb20tcGFja2FnZXMKCiAgIyBUbyBhZGQgY3VzdG9tIGZvbnRzIHRvIHlvdXIgYXBwbGljYXRpb24sIGFkZCBhIGZvbnRzIHNlY3Rpb24gaGVyZSwKICAjIGluIHRoaXMgImZsdXR0ZXIiIHNlY3Rpb24uIEVhY2ggZW50cnkgaW4gdGhpcyBsaXN0IHNob3VsZCBoYXZlIGEKICAjICJmYW1pbHkiIGtleSB3aXRoIHRoZSBmb250IGZhbWlseSBuYW1lLCBhbmQgYSAiZm9udHMiIGtleSB3aXRoIGEKICAjIGxpc3QgZ2l2aW5nIHRoZSBhc3NldCBhbmQgb3RoZXIgZGVzY3JpcHRvcnMgZm9yIHRoZSBmb250LiBGb3IKICAjIGV4YW1wbGU6CiAgIyBmb250czoKICAjICAgLSBmYW1pbHk6IFNjaHlsZXIKICAjICAgICBmb250czoKICAjICAgICAgIC0gYXNzZXQ6IGZvbnRzL1NjaHlsZXItUmVndWxhci50dGYKICAjICAgICAgIC0gYXNzZXQ6IGZvbnRzL1NjaHlsZXItSXRhbGljLnR0ZgogICMgICAgICAgICBzdHlsZTogaXRhbGljCiAgIyAgIC0gZmFtaWx5OiBUcmFqYW4gUHJvCiAgIyAgICAgZm9udHM6CiAgIyAgICAgICAtIGFzc2V0OiBmb250cy9UcmFqYW5Qcm8udHRmCiAgIyAgICAgICAtIGFzc2V0OiBmb250cy9UcmFqYW5Qcm9fQm9sZC50dGYKICAjICAgICAgICAgd2VpZ2h0OiA3MDAKICAjCiAgIyBGb3IgZGV0YWlscyByZWdhcmRpbmcgZm9udHMgZnJvbSBwYWNrYWdlIGRlcGVuZGVuY2llcywKICAjIHNlZSBodHRwczovL2ZsdXR0ZXIuZGV2L2N1c3RvbS1mb250cy8jZnJvbS1wYWNrYWdlcwo=
Free Resources