I have a Flutter app with a "Create Account" form that has a field for Username. Upon entering a username and hitting the "Submit" button, my validator functions run for the form. I would like to query my Firestore database and ensure that the username entered isn't already taken.
My validator
(in the Username form):
validator: (value) {
Future<bool> usernameTaken = uniqueCheck(value);
if (usernameTaken) {
return 'Username is already taken!';
} else {
return null;
}
My uniqueCheck
function:
Future<bool> uniqueCheck(String? value) async {
bool alreadyTaken = false;
var snapshot = await FirebaseFirestore.instance
.collection('users')
.where('username', isEqualTo: value)
.get();
snapshot.docs.forEach((result) {
alreadyTaken = true;
});
return alreadyTaken;
}
The trouble is my validator
finishes before my uniqueCheck
function can return with the proper result (such as if the username is taken and usernameTaken
is true
. I thought await
would fix this, but apparently not.
What am I doing wrong here?
CodePudding user response:
Try this:
validator: (value) async {
Future<bool> usernameTaken = await uniqueCheck(value);
if (usernameTaken) {
return 'Username is already taken!';
} else {
return null;
}
}
CodePudding user response:
SOLUTION: I figured it out. Validators can't be async so the solution was to call the uniqueCheck
function in the onPressed
function of the Submit button. I could then properly await
to see if the email was taken and then I called setState(){}
to redraw the screen.
onPressed: () async {
emailTaken = await uniqueCheck(emailKey.currentState!.value);
setState(() {});
if (formKey.currentState!.validate()) {
formKey.currentState?.save();
// {... add to database ...}
// {... navigate to successful sign-in screen ...}
}
},
Note that the emailTaken
bool is global to this scope so that when setState(){}
is called, the validator
in the email field will pick it up as true.
Email field form validator function:
validator: (value) {
if ((value!.isEmpty) | !(value.contains('@'))) {
return 'Please enter a valid email address.';
} else if (emailTaken) {
return 'Email is already taken!';
} else {
return null;
}
}