วิดเจ็ต Form และตัวควบคุม
ทำความเข้าใจวิธีใช้วิดเจ็ต `Form` เพื่อจัดการช่องข้อความหลายช่อง และควบคุมข้อมูลที่ผู้ใช้ป้อนด้วย `TextEditingController`
วิดเจ็ต Form และตัวควบคุม เป็นบทเรียน Flutter Mobile Development ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Flutter Mobile Development และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Flutter Mobile Development มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Forms: User Input Essentials
Forms are fundamental for almost any interactive mobile application. They allow users to input data, whether it's for logging in, signing up, updating profiles, or submitting information.
In Flutter, forms are built using a combination of widgets designed to handle user input efficiently and robustly.
Organizing Inputs with Form
The Form widget acts as a container for grouping multiple input fields. It provides a way to manage the state of these fields, validate them, and save their values all at once.
Think of it as the parent that oversees all its input children. Here's how to start a basic form structure:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('My Form App')),
body: Center(
child: Form(
child: Column(
children: [
// Form fields will go here
],
),
),
),
),
);
}
}Your First Input: TextFormField
While you can use TextField for input, TextFormField is specifically designed to work seamlessly within a Form widget. It offers built-in features for validation, saving, and error display.
Let's add a simple TextFormField to our form:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('My Form App')),
body: Center(
child: Form(
child: Column(
children: const [
Padding(
padding: EdgeInsets.all(16.0),
child: TextFormField(
decoration: InputDecoration(
labelText: 'Enter your name',
border: OutlineInputBorder(),
),
),
),
],
),
),
),
),
);
}
}Controlling Input: TextEditingController
To programmatically read, set, or modify the text in a TextFormField (or TextField), you use a TextEditingController. It acts as a communication bridge between your code and the text input widget.
It's crucial to dispose of controllers when they're no longer needed to prevent memory leaks, typically in the dispose() method of a StatefulWidget.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _myController = TextEditingController();
@override
void dispose() {
_myController.dispose(); // Important: dispose the controller!
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Controller Demo')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField( // Using TextField for clarity
controller: _myController,
decoration: const InputDecoration(
labelText: 'Type something',
border: OutlineInputBorder(),
),
),
),
),
),
);
}
}Linking Controller & TextFormField
Now, let's connect our TextEditingController to a TextFormField. This allows us to access the text entered by the user directly from the controller, for example, when a button is pressed.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _nameController = TextEditingController();
@override
void dispose() {
_nameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Controller Link')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Your Name',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
print('Name: ${_nameController.text}');
},
child: const Text('Get Name'),
),
],
),
),
),
);
}
}Managing Form State with GlobalKey
To interact with the Form widget itself – for example, to validate all its fields or save their state – you need a way to reference it. This is done using a GlobalKey<FormState>.
The GlobalKey provides access to the Form's internal state, allowing you to trigger actions like validate() or save() on all its children.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _formKey = GlobalKey<FormState>(); // Declare the GlobalKey
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('GlobalKey Demo')),
body: Form(
key: _formKey, // Assign the GlobalKey to the Form
child: Column(
children: const [
Padding(
padding: EdgeInsets.all(16.0),
child: TextFormField(
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
),
),
],
),
),
),
);
}
}Submitting Your Form
Combining Form, GlobalKey, and TextEditingControllers allows you to build a functional form. When a submit button is pressed, you can use the _formKey to access the form's state and process the input.
Here's a login form example where we print the collected data upon submission.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
@override
void dispose() {
_usernameController.dispose();
_passwordController.dispose();
super.dispose();
}
void _submitForm() {
// In a real app, you'd add validation here (covered in next lesson)
print('Username: ${_usernameController.text}');
print('Password: ${_passwordController.text}');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Login Data')),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Login Form')),
body: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextFormField(
controller: _usernameController,
decoration: const InputDecoration(labelText: 'Username'),
),
TextFormField(
controller: _passwordController,
obscureText: true,
decoration: const InputDecoration(labelText: 'Password'),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: _submitForm,
child: const Text('Submit'),
),
),
],
),
),
),
),
);
}
}Retrieving All Form Inputs
When you have multiple TextFormField widgets in your form, each linked to its own TextEditingController, retrieving all user inputs is straightforward. You simply access the .text property of each controller.
This makes it easy to collect all necessary data when the user is ready to submit their information.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _emailController = TextEditingController();
final TextEditingController _phoneController = TextEditingController();
@override
void dispose() {
_emailController.dispose();
_phoneController.dispose();
super.dispose();
}
void _getData() {
print('Email: ${_emailController.text}');
print('Phone: ${_phoneController.text}');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Email: ${_emailController.text}, Phone: ${_phoneController.text}')),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Multi-Input Get')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: 10),
TextFormField(
controller: _phoneController,
decoration: const InputDecoration(labelText: 'Phone'),
keyboardType: TextInputType.phone,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _getData,
child: const Text('Show Data'),
),
],
),
),
),
);
}
}Resetting Input Fields
After a form submission, or if you want to provide a 'Clear' button, you can easily reset the text in a TextFormField. Simply call the .clear() method on its associated TextEditingController, or set its .text property to an empty string.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _inputController = TextEditingController();
@override
void dispose() {
_inputController.dispose();
super.dispose();
}
void _clearInput() {
_inputController.clear(); // Clears the text in the TextFormField
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Clear Input Demo')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextFormField(
controller: _inputController,
decoration: const InputDecoration(
labelText: 'Type here',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: _clearInput,
child: const Text('Clear Text'),
),
],
),
),
),
);
}
}Form & Controller Check
Test your understanding of Flutter forms and controllers.
Recap: Forms & Controllers
In this lesson, we explored the foundational elements for building user input forms in Flutter:
- The
Formwidget acts as a parent container for managing multiple input fields. TextFormFieldis the specialized widget for text input within aForm, offering built-in form integration.- The
TextEditingControllerallows you to programmatically control, read, and modify the text in an input field. - A
GlobalKey<FormState>is used to access theForm's state, enabling actions like validation or saving. - Remember to dispose of your
TextEditingControllers to prevent memory leaks!
Next, we'll dive deeper into input validation techniques to ensure your forms collect correct and useful data!
คำถามที่พบบ่อย
บทเรียน “วิดเจ็ต Form และตัวควบคุม” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “วิดเจ็ต Form และตัวควบคุม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Flutter Mobile Development ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Flutter Mobile Development มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “วิดเจ็ต Form และตัวควบคุม”
ทำความเข้าใจวิธีใช้วิดเจ็ต `Form` เพื่อจัดการช่องข้อความหลายช่อง และควบคุมข้อมูลที่ผู้ใช้ป้อนด้วย `TextEditingController` คุณปฏิบัติ Flutter Mobile Development ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Flutter Mobile Development หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Flutter Mobile Development บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “วิดเจ็ต Form และตัวควบคุม” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Flutter Mobile Development นี้ได้ไหม
ได้ บทเรียน Flutter Mobile Development ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- วิดเจ็ต Form และตัวควบคุม
- เทคนิคการตรวจสอบข้อมูลนำเข้า
- ช่องแบบฟอร์มแบบกำหนดเอง
- โฟกัส แป้นพิมพ์ และประสบการณ์ผู้ใช้ด้านการป้อนข้อมูล