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
validator
property. - Integration with Forms: Works seamlessly with the
Form
widget 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
labelText
displays a hint to users. - Border: The
OutlineInputBorder
gives 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
validator
property simplifies error handling. - Customize Input for Specific Use Cases: Use
keyboardType
for different input types like emails, numbers, or passwords. - Focus Management: Use
FocusNode
to 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!