Working with TextEditingController
in Flutter is essential for managing and manipulating the text input in TextField
widgets. Below is a step-by-step guide on how to use TextEditingController
effectively:
Creating a TextEditingController
First, create an instance of TextEditingController
. You typically do this in the state class of a StatefulWidget.
import 'package:flutter/material.dart'; class MyTextFieldWidget extends StatefulWidget { @override _MyTextFieldWidgetState createState() => _MyTextFieldWidgetState(); } class _MyTextFieldWidgetState extends State { final TextEditingController _controller = TextEditingController(); @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('TextEditingController Example'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _controller, decoration: InputDecoration( labelText: 'Enter text', ), ), SizedBox(height: 20), ElevatedButton( onPressed: () { print('Text: ${_controller.text}'); }, child: Text('Print Text'), ), ], ), ), ); } } void main() => runApp(MaterialApp( home: MyTextFieldWidget(), ));
Setting Initial Value
You can set an initial value for the text field by assigning a value to the controller when you create it.
final TextEditingController _controller = TextEditingController(text: "Initial value");
Listening to Text Changes
To respond to changes in the text field, you can add a listener to the TextEditingController. This is good case when you need to have validation and feedback to the user in real/typing/ time
class _MyTextFieldWidgetState extends State { final TextEditingController _controller = TextEditingController(); @override void initState() { super.initState(); _controller.addListener(_printLatestValue); } void _printLatestValue() { print('Text field: ${_controller.text}'); } @override void dispose() { _controller.removeListener(_printLatestValue); _controller.dispose(); super.dispose(); } // ... rest of the code }
Example with a Form
Below is a more comprehensive example that uses TextEditingController
within a form and includes validation.
import 'package:flutter/material.dart'; class MyFormWidget extends StatefulWidget { @override _MyFormWidgetState createState() => _MyFormWidgetState(); } class _MyFormWidgetState extends State { final _formKey = GlobalKey(); final TextEditingController _controller = TextEditingController(); @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Form with TextEditingController'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( children: [ TextFormField( controller: _controller, decoration: InputDecoration( labelText: 'Enter text', ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; } return null; }, ), SizedBox(height: 20), ElevatedButton( onPressed: () { if (_formKey.currentState?.validate() ?? false) { print('Text: ${_controller.text}'); } }, child: Text('Submit'), ), SizedBox(height: 20), ElevatedButton( onPressed: () { _controller.clear(); }, child: Text('Clear Text'), ), ], ), ), ), ); } } void main() => runApp(MaterialApp( home: MyFormWidget(), ));
Text Input Types
You can specify the type of data you expect the user to input by setting the keyboardType
property of the TextField
widget. Here are some commonly used TextInputType
values:
- TextInputType.text: General text input.
- TextInputType.multiline: Multiline text input.
- TextInputType.number: Numerical input.
- TextInputType.phone: Phone number input.
- TextInputType.datetime: Date and time input.
- TextInputType.emailAddress: Email address input.
- TextInputType.url: URL input.
- TextInputType.visiblePassword: Password input (visible).
2. TextField Configuration Examples
Here’s how to use different TextInputType
values in a TextField
:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('TextField Input Types'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( keyboardType: TextInputType.text, decoration: InputDecoration( labelText: 'Text Input', ), ), SizedBox(height: 16), TextField( keyboardType: TextInputType.multiline, maxLines: 3, decoration: InputDecoration( labelText: 'Multiline Input', ), ), SizedBox(height: 16), TextField( keyboardType: TextInputType.number, decoration: InputDecoration( labelText: 'Number Input', ), ), SizedBox(height: 16), TextField( keyboardType: TextInputType.phone, decoration: InputDecoration( labelText: 'Phone Input', ), ), SizedBox(height: 16), TextField( keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email Input', ), ), SizedBox(height: 16), TextField( keyboardType: TextInputType.url, decoration: InputDecoration( labelText: 'URL Input', ), ), SizedBox(height: 16), TextField( keyboardType: TextInputType.visiblePassword, decoration: InputDecoration( labelText: 'Password Input', ), ), ], ), ), ), ); } }
Additional TextField Properties
- obscureText: Set to
true
for password fields to hide the text input. - maxLines: Specify the maximum number of lines for multiline input.
- maxLength: Limit the number of characters.
- inputFormatters: Use
inputFormatters
to control and validate the input format. - autofocus: Automatically focus the
TextField
when the widget is built. - textCapitalization: Control capitalization (e.g.,
TextCapitalization.sentences
,TextCapitalization.words
).
Example with Additional Properties
TextField( keyboardType: TextInputType.text, obscureText: true, maxLength: 20, decoration: InputDecoration( labelText: 'Password', hintText: 'Enter your password', border: OutlineInputBorder(), ), )
You cour read more about InputDecoration :
- https://api.flutter.dev/flutter/material/InputDecoration-class.html
- Floating Label: https://stackoverflow.com/questions/52487698/textfield-with-animated-hint-label
Input Formatters
You can use input formatters to control and validate the input. For example, to restrict input to digits only:
import 'package:flutter/services.dart'; TextField( keyboardType: TextInputType.number, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, ], decoration: InputDecoration( labelText: 'Digits Only', ), )
asd
TextField with Form Validation
You can also use a TextFormField
within a Form
widget for more advanced form validation:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('TextField with Form Validation'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: MyForm(), ), ), ); } } class MyForm extends StatefulWidget { @override _MyFormState createState() => _MyFormState(); } class _MyFormState extends State { final _formKey = GlobalKey(); @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( children: [ TextFormField( keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'Email', ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter an email'; } if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) { return 'Please enter a valid email'; } return null; }, ), SizedBox(height: 16), ElevatedButton( onPressed: () { if (_formKey.currentState?.validate() ?? false) { // Process data } }, child: Text('Submit'), ), ], ), ); } }
Capsulate the disposable part of TextEditingController
- Write boilerplate dispose every time
- Write custom wrapper with constructor fields
- initial value,
- change listener,
- errors, loading/disabled states
- didUpdateWidget inside for proper changes of state
- use feature of the state management solution. For example rx_bloc have a wrapper for textfields: https://www.primeholding.com/insights/building-forms-in-flutter
By leveraging these options and properties, you can create a wide range of input fields tailored to your application’s requirements.
Image used from https://pixabay.com/photos/pen-office-authority-form-2398693/
I’ve written more Flutter Articles that you may check out: https://programtom.com/dev/?s=flutter