構建帶驗證的表單
如何構建一個能驗證輸入的表單。
應用經常需要使用者在文字框中輸入資訊。例如,你可能需要使用者透過電子郵件地址和密碼組合來登入。
為了使應用安全且易於使用,請檢查使用者提供的資訊是否有效。如果使用者正確填寫了表單,則處理相關資訊。如果使用者提交了錯誤資訊,則顯示友好的錯誤提示,告知他們哪裡出了問題。
在這個示例中,透過以下步驟學習如何為包含單個文字框的表單新增驗證:
- 建立一個包含
GlobalKey的Form。 - 新增一個帶有驗證邏輯的
TextFormField。 - 建立一個按鈕來驗證並提交表單。
1. 建立一個包含 GlobalKey 的 Form
#
建立一個 Form。Form 元件充當容器,用於對多個表單欄位進行分組和驗證。
建立表單時,提供一個 GlobalKey。這會為你的 Form 分配一個唯一識別符號。它還允許你在後續步驟中對錶單進行驗證。
將表單建立為 StatefulWidget。這樣你就可以一次性建立唯一的 GlobalKey<FormState>()。然後,你可以將其儲存為變數,並在不同位置訪問它。
如果你將其設為 StatelessWidget,則需要將此鍵儲存在*某處*。由於這非常消耗資源,因此你不會希望在每次執行 build 方法時都生成一個新的 GlobalKey。
import 'package:flutter/material.dart';
// Define a custom Form widget.
class MyCustomForm extends StatefulWidget {
const MyCustomForm({super.key});
@override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
// Define a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a `GlobalKey<FormState>`,
// not a GlobalKey<MyCustomFormState>.
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: const Column(
children: <Widget>[
// Add TextFormFields and ElevatedButton here.
],
),
);
}
}
2. 新增一個帶有驗證邏輯的 TextFormField
#
儘管 Form 已經就位,但它還沒有讓使用者輸入文字的方式。這是 TextFormField 的工作。TextFormField 元件會渲染一個 Material Design 風格的文字框,並在出現驗證錯誤時顯示提示。
透過為 TextFormField 提供 validator() 函式來驗證輸入。如果使用者的輸入無效,validator 函式應返回一個包含錯誤訊息的 String。如果沒有錯誤,驗證器必須返回 null。
在本例中,建立一個 validator 以確保 TextFormField 不為空。如果為空,則返回一條友好的錯誤訊息。
TextFormField(
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
3. 建立一個用於驗證並提交表單的按鈕
#現在你已經擁有了一個帶有文字框的表單,接下來提供一個按鈕,供使用者點選以提交資訊。
當用戶嘗試提交表單時,檢查表單是否有效。如果有效,顯示成功訊息。如果無效(例如文字框為空),則顯示錯誤訊息。
ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false otherwise.
if (_formKey.currentState!.validate()) {
// If the form is valid, display a snackbar. In the real world,
// you'd often call a server or save the information in a database.
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
這是如何工作的?
#要驗證表單,請使用第 1 步中建立的 _formKey。你可以使用 _formKey.currentState 訪問器來獲取 FormState,它是 Flutter 在構建 Form 時自動建立的。
FormState 類包含 validate() 方法。當呼叫 validate() 方法時,它會為表單中的每個文字框執行 validator() 函式。如果一切正常,validate() 方法返回 true。如果任何文字框包含錯誤,validate() 方法會重新構建表單以顯示錯誤訊息,並返回 false。
互動示例
#import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
const appTitle = 'Form Validation Demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(title: const Text(appTitle)),
body: const MyCustomForm(),
),
);
}
}
// Create a Form widget.
class MyCustomForm extends StatefulWidget {
const MyCustomForm({super.key});
@override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a GlobalKey<FormState>,
// not a GlobalKey<MyCustomFormState>.
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false otherwise.
if (_formKey.currentState!.validate()) {
// If the form is valid, display a snackbar. In the real world,
// you'd often call a server or save the information in a database.
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
),
],
),
);
}
}
要了解如何檢索這些值,請檢視獲取文字框的值食譜。