如何在更新 Firestore 数据库之前验证 Flutter 文本表单字段
How to validate Flutter Text Form Field before updating Firestore database
在将数据上传到 Firestore 数据库之前,我无法验证文本表单字段。 Firestore 没有任何问题,只是我编写代码的方式有问题。
验证是检查文本字段不为null或为空,与Flutter codelab相同。如果文本字段为空,则应显示一条错误消息,并且用户应停留在同一页面上,直到文本字段有数据为止。一旦文本字段有效,数据就应该保存到 Firestore,页面上应该会出现一个 snackbar 确认信息,用户应该被导航到另一个页面。
使用我编写的代码,用户导航到新页面,即使所有文本表单字段都为空(无效),也会显示快餐栏消息。我试图删除额外的代码,以便更容易查看代码。在我的表单中,我有三个具有相同验证规则的文本字段。任何帮助将不胜感激。谢谢
我的文本表单域:
TextFormField(
labelText: 'Trivia Game Url',
onChanged: (val) {
triviaGameImageURL = val as String;
},
controller: _triviaGameImageURLController,
validator: _triviaGameImageURLValidator,
),
验证方法:
String? _triviaGameImageURLValidator(value) {
if (value == null || value.isEmpty) {
return 'Image Url is required';
}
return null;
}
用户点击按钮时更新 Firestore 的方法:
Future<void> createFirestoreTriviaGame() async {
final form = _formKey.currentState;
if (form!.validate()) {
setState(() {
_isLoading = true;
});
String triviaGameID = const Uuid().v4();
Map<String, dynamic> triviaGameMap = {
FirebaseString.triviaGameID: triviaGameID,
FirebaseString.triviaGameImageURL: triviaGameImageURL,
};
await firestoreMethods
.addTriviaGameData(
triviaGameData: triviaGameMap,
triviaGameID: triviaGameID,
)
.then((value) {
setState(() {
_isLoading = false;
});
});
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(SnackBarString.triviaGameCreated),
),
);
Timer(const Duration(seconds: 2), () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const AddTriviaGamePage(),
),
);
});
}
您需要将文本字段包装在 form 小部件中并为表单小部件分配一个表单键
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Form(
key: formKey,
child: Column(
children: [
... your text fields
// validate
if (formKey.currentState!.validate()) {
在您的代码中,快餐栏和导航位于 if (form!.validate())
块之外。只需扩展此块以包含您只想在有效表单上执行的所有内容,并在验证失败时显示一条消息。
只有在 Firestore 异步调用完成后,成功保存才会出现快餐栏和导航。我建议不要将 async/await
和 .then
混用,它们是一样的。如此简单的 await
Firestore 方法,将其放入 try/catch
块中并在成功时执行 snackbar 和导航。
在将数据上传到 Firestore 数据库之前,我无法验证文本表单字段。 Firestore 没有任何问题,只是我编写代码的方式有问题。
验证是检查文本字段不为null或为空,与Flutter codelab相同。如果文本字段为空,则应显示一条错误消息,并且用户应停留在同一页面上,直到文本字段有数据为止。一旦文本字段有效,数据就应该保存到 Firestore,页面上应该会出现一个 snackbar 确认信息,用户应该被导航到另一个页面。
使用我编写的代码,用户导航到新页面,即使所有文本表单字段都为空(无效),也会显示快餐栏消息。我试图删除额外的代码,以便更容易查看代码。在我的表单中,我有三个具有相同验证规则的文本字段。任何帮助将不胜感激。谢谢
我的文本表单域:
TextFormField(
labelText: 'Trivia Game Url',
onChanged: (val) {
triviaGameImageURL = val as String;
},
controller: _triviaGameImageURLController,
validator: _triviaGameImageURLValidator,
),
验证方法:
String? _triviaGameImageURLValidator(value) {
if (value == null || value.isEmpty) {
return 'Image Url is required';
}
return null;
}
用户点击按钮时更新 Firestore 的方法:
Future<void> createFirestoreTriviaGame() async {
final form = _formKey.currentState;
if (form!.validate()) {
setState(() {
_isLoading = true;
});
String triviaGameID = const Uuid().v4();
Map<String, dynamic> triviaGameMap = {
FirebaseString.triviaGameID: triviaGameID,
FirebaseString.triviaGameImageURL: triviaGameImageURL,
};
await firestoreMethods
.addTriviaGameData(
triviaGameData: triviaGameMap,
triviaGameID: triviaGameID,
)
.then((value) {
setState(() {
_isLoading = false;
});
});
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(SnackBarString.triviaGameCreated),
),
);
Timer(const Duration(seconds: 2), () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const AddTriviaGamePage(),
),
);
});
}
您需要将文本字段包装在 form 小部件中并为表单小部件分配一个表单键
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Form(
key: formKey,
child: Column(
children: [
... your text fields
// validate
if (formKey.currentState!.validate()) {
在您的代码中,快餐栏和导航位于 if (form!.validate())
块之外。只需扩展此块以包含您只想在有效表单上执行的所有内容,并在验证失败时显示一条消息。
只有在 Firestore 异步调用完成后,成功保存才会出现快餐栏和导航。我建议不要将 async/await
和 .then
混用,它们是一样的。如此简单的 await
Firestore 方法,将其放入 try/catch
块中并在成功时执行 snackbar 和导航。