【问题标题】:How to use form validation to verify that document exists inside collection Firestore with Flutter如何使用表单验证通过 Flutter 验证集合 Firestore 中是否存在文档
【发布时间】:2020-03-20 23:48:45
【问题描述】:

我想使用表单验证来验证 Firestore 集合中的文档是否存在 Flutter。如果不是,我将向用户返回带有错误消息的字符串。用户只能在填写数据库中已经存在的名称后才能继续(否则他们无法订阅正确的环境)。 我在我的代码中使用FormTextFormField 和验证器。

下面我已将我的stateful widget 包含在Form

import 'package:flutter/material.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';

class BuildingScreen extends StatefulWidget {

  @override
  _BuildingScreenState createState() => _BuildingScreenState();
}

class _BuildingScreenState extends State<BuildingScreen> {
  final _formKey = GlobalKey<FormState>();
  bool showSpinner = false;
  String environment;
  bool _autoValidate = false;

  void _validateInputs() {
    if (_formKey.currentState.validate()) {
      _formKey.currentState.save();
      setState(() {
        showSpinner = true;
      });
    } else {
      setState(() {
        _autoValidate = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ModalProgressHUD(
        inAsyncCall: showSpinner,
              child: Column(
                children: <Widget>[
                  Form(
                    key: _formKey,
                    child: Column(
                      children: <Widget>[
                        TextFormField(
                          textAlign: TextAlign.center,
                          validator: validateEnvironment,
                          onSaved: (String value) {
                            environment = value;
                          },
                        ),
                        RoundedButton(
// the RoundedButton is just a material button with some custom padding
                          buttonTitle: 'Verify',
                          onPressed: () async {
                            _validateInputs();

                            try {
                              if (_formKey.currentState.validate()) {
                                Navigator.pushNamed(
                                    context, RoosterEnvironment.id);
                              }
                              setState(() {
                                showSpinner = false;
                              });
                            } catch (e) {
                              print(e);
                            }
                          },
                        ),
                      ],
                    ),
                  ),
                ],
              ),
      ),
    );
  }
}

下面是 validateEnvironment 函数:

import 'package:cloud_firestore/cloud_firestore.dart';

String validateEnvironment(String value) {
  if (value != Firestore.instance.collection('environments').document(value).documentID)
    return 'Environment not on the list';
  else
    return null;
}

在我的 firestore 数据库中,我有一个名为“environments”的集合。在这个集合中,我保存了一个名为“test”的文档,其中包含“name:test”字段。现在(value != Firestore.instance.collection('environments').document(value).documentID) 将始终为假,因为firestore 实例返回插入TextFormField 的任何值。当我用(value != 'test') 替换它时,验证器确实可以正常工作。我还尝试将集合命名为“test”,然后验证它是否存在,如下所示:(value != Firestore.instance.collection('test')) 但这会返回一个“collectionReference”实例。

我想知道是否甚至可以对表单验证进行此检查,还是应该以完全不同的方式完成?对此的任何帮助将不胜感激!

更新

感谢一些帮助,我更新了我的代码。现在我使用TextEditingController 和Griffo 的代码来检查文本字段中的值是否存在于Firestore 中。当它还不存在时,我还没有添加错误消息,但下面我包含了适合我的代码。

final _controller = TextEditingController();

static Future<bool> validateEnvironment(String docID) async {
    bool exists = false;
    try {
      await Firestore.instance
          .document("environments/$docID")
          .get()
          .then((doc) {
        if (doc.exists)
          exists = true;
        else
          exists = false;
      });
      print(exists);
      return exists;
    } catch (e) {
      return false;
    }
  }

  void _formvalidate(String docId) async {
    validateEnvironment(docId).then((value) {
      if (value == true) {
        _updateData();
        Navigator.pushNamed(context, RoosterEnvironment.id);
      } else {
      // do something
      }
    });
  }

onPressed 中,我只包含以下内容:

onPressed: () {
       environment = _controller.text;
       _formvalidate(environment);
},

再次感谢!

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    我认为 Firestore 可以查询包含所有文档的所有集合数据,但 Firestore 无法查询不存在的文档名称。因此,您可以先接收集合中的所有文档名称,然后对其进行验证。 请试试这个

    final snapshots = Firestore.instance.collection('environments').snapshots();
    
    final docNameList = snapshots.map((snapshot) {
      final result = snapshot.documents
          .map((snapshot) =>  snapshot.documentID).toList();
      return result;
    });
    

    你可以像这样验证

    String validateEnvironment(String value) {
       if (!docNameList.data.contains(value))
         return 'Environment not on the list';
      else
         return null;
    }
    

    如果有错误请告诉我。

    【讨论】:

    • 也许我应该提到我仍然是一个颤振初学者。我尝试实现我认为我理解的代码,但是当我尝试它时它没有验证,即它将所有值作为“列表”传递。我尝试打印 docNameList ,然后它给了我一个值 '_MapStream>''' 的实例
    • 也许我忘了这是快照。请尝试 !docNameList.data.contains(value)
    【解决方案2】:

    您可以尝试通过运行查询来搜索 doc IDS,以检查您拥有的 ID 是否已经存在于该集合中。我们从一个静态方法开始

         static Future<bool> validateEnvironment(String docID) async {
        bool exists = false;
        try {
          await Firestore.instance.document("environments/$docID").get().then((doc) {
            if (doc.exists)
              exists = true;
            else
              exists = false;
          });
          return exists;
        } catch (e) {
          return false;
        }
    }
    

    终于从你的班级调用函数

     void  _formvalidate(String docId)async{
        validateEnvironment(docId).then((value) {
          if (!value) {
           //file not found do dome stuff
    ....
          } else {
           //document exists do some stuff
          }
    });
        }
    

    【讨论】:

    • 谢谢!我不得不更新我的代码,但你的回答对我有帮助!
    猜你喜欢
    • 2021-09-01
    • 2020-05-18
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 2011-07-21
    • 2015-11-29
    相关资源
    最近更新 更多