Using TextFormField for Input in Flutter: A Beginner's Guide
The TextFormField widget is a fundamental building block for creating forms and handling user input in Flutter. It combines a text input field with built-in validation, making it ideal for scenarios like login forms, registration forms, or search bars.
This guide will help you understand how to use TextFormField effectively and implement features like validation and customization.
What is TextFormField?
The TextFormField widget is a more advanced version of the basic TextField. It provides:
- Validation: Built-in support for input validation using the
validatorproperty. - Integration with Forms: Works seamlessly with the
Formwidget to manage state and validation. - Customizable Input: Supports features like labels, hints, icons, and keyboard types.
Basic Example of TextFormField
Here’s a simple example of a TextFormField to accept a user's name:
TextFormField(
decoration: InputDecoration(
labelText: 'Enter your name',
border: OutlineInputBorder(),
),
);
Key Features:
- Label: The
labelTextdisplays a hint to users. - Border: The
OutlineInputBordergives a framed appearance to the input field.
Adding Validation
Validation ensures that users provide the correct input. Use the validator property to define validation logic.
Example: Validating Non-Empty Input
TextFormField(
decoration: InputDecoration(
labelText: 'Email',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'This field cannot be empty';
}
return null;
},
);
Example: Validating Email Format
TextFormField(
decoration: InputDecoration(
labelText: 'Email',
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter an email';
}
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return 'Enter a valid email address';
}
return null;
},
);Managing Input with Controllers
To retrieve or modify the input programmatically, use a TextEditingController.
Example: Accessing Input Value
final TextEditingController _controller = TextEditingController();
TextFormField(
controller: _controller,
decoration: InputDecoration(labelText: 'Username'),
);
ElevatedButton(
onPressed: () {
print('Input value: ${_controller.text}');
},
child: Text('Submit'),
);
Customizing Appearance
The InputDecoration property allows you to customize the appearance of the TextFormField.
Example: Adding Icons and Styling
TextFormField(
decoration: InputDecoration(
labelText: 'Password',
hintText: 'Enter your password',
prefixIcon: Icon(Icons.lock),
border: OutlineInputBorder(),
),
obscureText: true, // Hides input for passwords
);
Custom Styling
You can style the field further with TextStyle and themes:
TextFormField(
decoration: InputDecoration(
labelText: 'Custom Styled Input',
labelStyle: TextStyle(color: Colors.blue, fontSize: 16),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green, width: 2),
),
),
);
Handling Focus with FocusNode
The FocusNode lets you control and listen to focus changes.
Example: Moving Focus Programmatically
final FocusNode _focusNode1 = FocusNode();
final FocusNode _focusNode2 = FocusNode();
TextFormField(
focusNode: _focusNode1,
decoration: InputDecoration(labelText: 'Field 1'),
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_focusNode2);
},
);
TextFormField(
focusNode: _focusNode2,
decoration: InputDecoration(labelText: 'Field 2'),
);
Example: Login Form with TextFormField
Here’s a complete example using TextFormField for a login form:
import 'package:flutter/material.dart';
class LoginForm extends StatefulWidget {
@override
_LoginFormState createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
void _submitForm() {
if (_formKey.currentState!.validate()) {
print('Email: ${_emailController.text}');
print('Password: ${_passwordController.text}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login Form')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) {
return 'Enter a valid email address';
}
return null;
},
),
SizedBox(height: 16),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
}
if (value.length < 6) {
return 'Password must be at least 6 characters long';
}
return null;
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _submitForm,
child: Text('Login'),
),
],
),
),
),
);
}
}
Tips for Using TextFormField Effectively
- Use Controllers for Programmatic Input Management: Easily retrieve and manipulate text values.
- Leverage Built-In Validation: The
validatorproperty simplifies error handling. - Customize Input for Specific Use Cases: Use
keyboardTypefor different input types like emails, numbers, or passwords. - Focus Management: Use
FocusNodeto enhance user navigation between fields.
With these insights, you’re ready to incorporate TextFormField into your Flutter projects for a seamless input experience. Experiment with its customization options and validation capabilities to build intuitive user forms!