6

In my app the user has to insert a name in the textformfield. While the user is writing a query should be made to the database, that controls if the name already exists. This query returns the number of how many times the name exists. Till now I am able to make it when I press a button.

This is the function that returns the count of the names:

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

And this is the TextFormField, which should be validated async:

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";
    },
 )

The error of the code is:

The argument type Future can't be assigned to the parameter type String

I do know what the error means. But I do not know how to work around could look like. It would be awesome if somebody could help me.

I have found a solution.

My Code looks now like this:

//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;
  }
  • [This](https://stackoverflow.com/questions/52584520/flutter-firebase-validation-of-form-field-inputs?rq=1) is the workaround, that did the job for me. –  Nov 07 '18 at 17:35
  • 1
    Possible duplicate of [Flutter firebase validation of form field inputs](https://stackoverflow.com/questions/52584520/flutter-firebase-validation-of-form-field-inputs) – mirkancal Aug 03 '19 at 14:57
  • Works perfectly fine for me, Thank you very much! – Kőne Mátyás Sep 01 '19 at 17:45
  • 1
    If you came up with your own answer, please add an answer to your question and mark it as correct. This will help other users. – João Soares Mar 09 '20 at 14:46

2 Answers2

6

Perhaps you could run your async check using the onChange handler and set a local variable to store the result.

Something like:

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,
)
Your Friend Ken
  • 8,184
  • 2
  • 30
  • 35
2

I wanted a same behavior for one of our apps and ended up writing a widget (which I recently published to pub.dev).

enter image description here

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

You can pass in a Future<bool> function for the validator and set an interval before the text is sent to server.

The code is available on github.

snippetkid
  • 250
  • 3
  • 15