dart Flutter -TextFormField的异步验证器

2w3rbyxf  于 2023-03-10  发布在  Flutter
关注(0)|答案(3)|浏览(186)

在我的应用程序中,用户必须在textformfield中插入一个名字。当用户在写一个查询时,应该对数据库进行查询,这控制着这个名字是否已经存在。这个查询返回这个名字存在的次数。到目前为止,我可以在按下一个按钮时进行查询。
此函数返回名称的计数:

checkRecipe(String name) async{
    await db.create();
    int count = await db.checkRecipe(name);
    print("Count: "+count.toString());
    if(count > 0) return "Exists";
  }

这是TextFormField,应该异步验证:

TextField(
    controller: recipeDescription,
    decoration: InputDecoration(
       hintText: "Beschreibe dein Rezept..."
    ),
    keyboardType: TextInputType.multiline,
    maxLines: null,
    maxLength: 75,
    validator: (text) async{ //Returns an error
       int count = await checkRecipe(text);
       if (count > 0) return "Exists";
    },
 )

代码的错误是:
无法将参数类型Future分配给参数类型String
我知道这个错误是什么意思。但是我不知道如何解决这个问题。如果有人能帮助我,那就太好了。

我找到了solution

“我的代码”现在如下所示:

//My TextFormField validator
validator: (value) => checkRecipe(value) ? "Name already taken" : null,

//the function
  checkRecipe<bool>(String name) {
    bool _recExist = false;
    db.create().then((nothing){
      db.checkRecipe(name).then((val){
        if(val > 0) {
          setState(() {
            _recExist = true;
          });
        } else {          
          setState(() {
            _recExist = false;
          });
        }
      });
    });
    return _recExist;
  }
6ie5vjzr

6ie5vjzr1#

也许您可以使用onChange处理程序运行async检查,并设置一个局部变量来存储结果。
比如:

TextFormField(
  controller: recipeDescription,
  decoration: InputDecoration(hintText: "Beschreibe dein Rezept..."),
  keyboardType: TextInputType.multiline,
  maxLines: null,
  maxLength: 75,
  onChanged: (text) async {
    final check = await checkRecipe(text);
    setState(() => hasRecipe = check);
  },
  validator: (_) => (hasRecipe) ? "Exists" : null,
)
uyto3xhc

uyto3xhc2#

我希望我们的一个应用程序也有同样的行为,最后写了一个小部件(我最近发布到pub.dev)。

AsyncTextFormField(
    controller: controller,
    validationDebounce: Duration(milliseconds: 500),
    validator: isValidPasscode,
    hintText: 'Enter the Passcode')

您可以为validator传入一个Future<bool>函数,并设置文本发送到服务器之前的时间间隔。
该代码在github上提供。

kkih6yb8

kkih6yb83#

试试这样的方法:

import 'dart:async';

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget {
  const TestPage({super.key});

  @override
  State<StatefulWidget> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  final TextEditingController _recipeController = TextEditingController();
  bool? _isRecipeValid;

  bool _validateAndSave() {
    final FormState? form = _formKey.currentState;

    if (form?.validate() ?? false) {
      form?.save();

      return true;
    } else {
      return false;
    }
  }

  Future<bool> _checkRecipe() async {
    // Change to any number to test the functionality
    const int returnValue = 1;
    // This is just a simulation of async stuff
    // Do whatever you want here instead
    final int count = await Future.delayed(const Duration(seconds: 1), () => returnValue);

    return count > 0 ? true : false;
  }

  Future<void> _validateAndSubmit() async {
    _isRecipeValid = await _checkRecipe();

    if (_validateAndSave()) {
      // If validation succeed, do whatever you want here
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
            child: Container(
                padding: const EdgeInsets.all(16),
                child: Form(
                    key: _formKey,
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: _recipeItems())))));
  }

  List<Widget> _recipeItems() {
    return [
      TextFormField(
          controller: _recipeController,
          decoration:
              const InputDecoration(hintText: 'Beschreibe dein Rezept...'),
          keyboardType: TextInputType.multiline,
          maxLines: null,
          maxLength: 75,
          validator: (_) => _isRecipeValid ?? false ? 'Exists' : null),
      const SizedBox(height: 10),
      ElevatedButton(
          onPressed: _validateAndSubmit,
          style: ElevatedButton.styleFrom(
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10))),
          child: const Text('Save')),
    ];
  }
}

相关问题