如何在更新 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 和导航。