How to validate Flutter Text Form Field before updating Firestore database

419

Solution 1

In your code the snackbar and navigation is outside the if (form!.validate()) block. Simply extend this block to include everything that you want to execute only on a valid form, and display a message if validation fails.

The snackbar and navigation should happen on successful save only, after Firestore async call completes. I recommend not to mix async/await with .then, these are the same. So simple await Firestore method, put this in a try/catch block and execute snackbar and navigation on success.

Solution 2

You need to wrap the textfield in a form widget and assign a form key to the form widget

 final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Form(
      key: formKey,
      child: Column(
        children: [
... your text fields

// validate 
    if (formKey.currentState!.validate()) {
Share:
419
Carleton Y
Author by

Carleton Y

Updated on November 26, 2022

Comments

  • Carleton Y
    Carleton Y over 1 year

    I'm having trouble validating a text form field before data is uploaded to the Firestore database. There aren't any issues with Firestore, only with the way I have written my code.

    The validation is to check that the text field is not null or empty, the same as the Flutter codelab. If the text field is empty an error message should appear and the user should remain on the same page until the text field has data. Once the text field is valid the data should be saved to Firestore, a snackbar confirmation should appear on the page and the user should be navigated to a different page.

    With the code I have written the user navigates to the new page and the snackbar message appears even if all of the text form fields are empty (invalid). I tried to remove extra code to make it easier to view the code. In my form I have three text fields with identical validation rules. Any help would be greatly appreciated. Thanks.

    My Text Form Field:

    TextFormField(
    labelText: 'Trivia Game Url',
    onChanged: (val) {
    triviaGameImageURL = val as String;
    },
    controller: _triviaGameImageURLController,
    validator: _triviaGameImageURLValidator,
    ),
    

    Validation method:

     String? _triviaGameImageURLValidator(value) {
          if (value == null || value.isEmpty) {
            return 'Image Url is required';
          }
          return null;
        }
    

    Method to update Firestore when user taps button:

    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(),
          ),
        );
      });
    }
    
  • Carleton Y
    Carleton Y about 2 years
    I believe this is the third time that you have answered one of my questions and each time it worked immediately. As I am sure you know you are correct and my code now works as desired. I will work to update the code to try/catch block as suggested. Thanks as always for your great help.
  • Carleton Y
    Carleton Y about 2 years
    Thanks for your answer. I didn't show enough code. My text form field is in a form as you have written.
  • Carleton Y
    Carleton Y about 2 years
    Try/catch block added and working perfectly also. Thanks again @peterkoltai!
  • Peter Koltai
    Peter Koltai about 2 years
    Good to hear, you are welcome!