Home > Software engineering >  TextFormFields disappear after resizing the screen - error: "Multiple widgets used the same Glo
TextFormFields disappear after resizing the screen - error: "Multiple widgets used the same Glo

Time:07-04

Currently I have the problem, that my TextFormFields disappear, when the user goes to 'Teilehmer werden', then back to 'Login' and then resize screen (example: https://gyazo.com/2b3d9351cfaf33e35490d79d2734f48c).

Here a video how it looks like, when I am using a smartphone: https://youtube.com/shorts/XFn_mMCutpk

I am getting the error: Multiple widgets used the same GlobalKey.

I don't really understand why it is happening, so I have added the full code in a github link below.

Does someone know why this is happening? Have I somehow messed up the TextFormFields? I am using different GlobalKeys for every TextFormField, so why is it happening?

Website: https://thebasics-fb4e8.web.app/#/login

login (authentication.dart) code:

import 'package:bestfitnesstrackereu/routing/route_names.dart';
import 'package:email_validator/email_validator.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../../provider/auth.dart';
import '../../widgets/loading_circle/loading_circle.dart';

//AuthenticationPage (Login page)

class AuthenticationPage extends StatefulWidget {
  const AuthenticationPage({Key key}) : super(key: key);

  @override
  State<AuthenticationPage> createState() => _AuthenticationPageState();
}

class _AuthenticationPageState extends State<AuthenticationPage> {
  var userData;
  static final List<GlobalKey<FormState>> _formKeys = [
    GlobalKey<FormState>(), GlobalKey<FormState>(),
  ];

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final authProvider = Provider.of<AuthProvider>(context);

    return Scaffold(
      body: SingleChildScrollView(
        child: Center(
          // checks the authentication status, when it is Authenticating, then return loading, else show the page
          child: authProvider.status == Status.Authenticating ? Loading() : Container(
            constraints: BoxConstraints(maxWidth: 440),
            padding: EdgeInsets.all(24),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Row(
                  children: [
                    Padding(
                      padding: EdgeInsets.only(right: 12),
                      child: Image.asset("assets/logo.png", width: 300,),
                    ),
                    Expanded(child: Container()),
                  ],
                ),

                SizedBox(
                  height: 30,
                ),

                Row(
                  children: [
                    Text("Login",
                      style: TextStyle(
                      fontSize: 30, fontWeight: FontWeight.bold
                    )),
                  ],
                ),

                SizedBox(height: 10,),

                Row(
                  children: [
                    Text(
                      "Wilkommen zurück zum Login",
                      style: TextStyle(
                      color: Colors.grey,))
                  ],
                ),

                SizedBox(height: 15,),

                Form(
                  key: _formKeys[0],
                  autovalidateMode: AutovalidateMode.always,
                  child: TextFormField(
                    validator: (email) => EmailValidator.validate(email) ? null : "Bitte gib eine gültige E-Mail an.",
                    controller: authProvider.emailController,
                    keyboardType: TextInputType.text,
                    decoration: InputDecoration(
                        labelText: "E-Mail",
                        hintText: "[email protected]",
                        suffixIcon: Icon(Icons.mail_outline,),
                        isDense: true,
                        border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(20)
                        )
                    ),
                  ),
                ),

                SizedBox(height: 15,),

                Form(
                  key: _formKeys[1],
                  autovalidateMode: AutovalidateMode.always,
                  child: TextFormField(
                    validator: (password) {
                      print(authProvider.validatePassword(password));
                      return authProvider.validatePassword(password);
                    },
                    controller: authProvider.passwordController,
                    obscureText: true,
                    decoration: InputDecoration(
                        labelText: "Passwort",
                        hintText: "******",
                        suffixIcon: Icon(Icons.lock_outline, color: Colors.grey,),
                        border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(20)
                        )
                    ),
                  ),
                ),

                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 25.0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      GestureDetector(
                        onTap: () {
                          authProvider.clearController();
                          Navigator.of(context).pushNamed(ForgotPasswordRoute);       // navigate to the forgot password page
                          },
                        child: Text(
                          'Passwort vergessen',
                          style: TextStyle(
                            color: Colors.blue[700],
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      )
                    ],
                  ),
                ),

                SizedBox(height: 15,),

                InkWell(
                  onTap: () async {

                    //check if email and password field is not empty
                    if(authProvider.emailController.text.trim().isEmpty || authProvider.passwordController.text.trim().isEmpty){
                      showDialog(context: context, builder: (BuildContext context){
                        return AlertDialog(
                          title: Text("Error: Bitte fülle das E-Mail- und Passwort-Feld aus."),
                          actions: [
                            TextButton(
                              child: Text("Ok"),
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                            )
                          ],
                        );
                      });
                    } else {

                    //checking if the email and password is valid
                    final emailFormkey = _formKeys[0].currentState;
                    final passwordFormkey = _formKeys[1].currentState;
                    if(emailFormkey.validate() && passwordFormkey.validate()){
                      print('validate email okok');

                    // input is the authProvider.emailController, which provides the written email from the user
                    // output are all the user informations in a Map<String, dynamic>
                    // used to check the status and role of the user
                    Map<String, dynamic> mapUserinformations = {};
                    mapUserinformations = await authProvider.getUserByEmail();

                    // checking if the admin/scientist exist
                    if (mapUserinformations != null){

                    //status from user = locked
                    if(mapUserinformations['status'] == 'gesperrt'){
                      showDialog(context: context, builder: (BuildContext context){
                        return AlertDialog(
                          title: Text("Error: Dein Account ist gesperrt"),
                          actions: [
                            TextButton(
                              child: Text("Ok"),
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                            )
                          ],
                        );
                      });
                    }

                    //status from user = deleted
                    if(mapUserinformations['status'] == 'gelöscht'){
                      showDialog(context: context, builder: (BuildContext context){
                        return AlertDialog(
                          title: Text("Error: Dein Account wurde gelöscht. Er existiert nicht mehr."),
                          actions: [
                            TextButton(
                              child: Text("Ok"),
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                            )
                          ],
                        );
                      });
                    }

                    //status from user = active
                    if(mapUserinformations['status'] == 'aktiv') {

                      //role from user = admin
                      if (mapUserinformations['role'] == 'Admin') {
                        print('admin - am einloggen');
                        if(!await authProvider.signIn()){      //signIn failed, then return "Login failed"
                          showDialog(context: context, builder: (BuildContext context){
                            return AlertDialog(
                              title: Text("Error: Login fehlgeschlagen. Falsche Kombination aus E-Mail und Passwort."),
                              actions: [
                                TextButton(
                                  child: Text("Ok"),
                                  onPressed: () {
                                    authProvider.clearController();
                                    Navigator.of(context).pop();
                                  },
                                )
                              ],
                            );
                          });
                        }
                        else {
                          authProvider.clearController();
                          Navigator.of(context).pushNamed(UsersAdministrationRoute);
                        }
                      }

                      //role from user = scientist
                      if (mapUserinformations['role'] == 'Wissenschaftler') {
                        print('scientist - am einloggen');
                        if(!await authProvider.signIn()){      //signIn failed, then return "Login failed"
                          showDialog(context: context, builder: (BuildContext context){
                            return AlertDialog(
                              title: Text("Error: Error: Login fehlgeschlagen. Falsche Kombination aus E-Mail und Passwort."),
                              actions: [
                                TextButton(
                                  child: Text("Ok"),
                                  onPressed: () {
                                    authProvider.clearController();
                                    Navigator.of(context).pop();
                                  },
                                )
                              ],
                            );
                          });
                        }
                        else {             //if signIn is success, then clear controller and navigate to User Scientist page
                          authProvider.clearController();
                          Navigator.of(context).pushNamed(UsersAdministrationRoute);
                        }
                      }

                      //role from user = user
                      if (mapUserinformations['role'] == 'User') {
                        print('user - kein zugriff');
                        showDialog(context: context, builder: (BuildContext context){
                          return AlertDialog(
                            title: Text("Error: Du hast keine Zugriffsberichtigung auf diesen Login."),
                            actions: [
                              TextButton(
                                child: Text("Ok"),
                                onPressed: () {
                                  authProvider.clearController();
                                  Navigator.of(context).pop();
                                },
                              )
                            ],
                          );
                        });
                      }
                    }
                  }else {
                      showDialog(context: context, builder: (BuildContext context){
                        return AlertDialog(
                          title: Text("Error: Ein Benutzer mit dieser E-Mail existiert nicht."),
                          actions: [
                            TextButton(
                              child: Text("Ok"),
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                            )
                          ],
                        );
                      });
                    }

                    }else{
                      print('validate email notgoodatall');
                      showDialog(context: context, builder: (BuildContext context){
                        return AlertDialog(
                          title: Text("Error: Bitte gebe eine gültige E-Mail an."),
                          actions: [
                            TextButton(
                              child: Text("Ok"),
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                            )
                          ],
                        );
                      });
                    }}},

                  child: Container(
                    decoration: BoxDecoration(color: Colors.deepPurple,
                    borderRadius: BorderRadius.circular(20)),
                    alignment: Alignment.center,
                    width: double.maxFinite,
                    padding: EdgeInsets.symmetric(vertical: 16),
                    child: Text(
                      "Login",
                      style: TextStyle(
                      color: Colors.white,
                    ),)
                )
                ),

                SizedBox(height: 15,),

                Row(
                  children: [
                    Expanded(
                        child: Divider(
                          height: 50,
                           color: Colors.grey[500],
                        )
                    ),
                    Padding(
                        padding: EdgeInsets.symmetric(horizontal: 20),
                      child: Text('Du bist noch nicht registriert?'),
                    ),
                    Expanded(
                        child: Divider(
                          height: 50,
                          color: Colors.grey[500],
                        )
                    ),
                  ],
                ),

                SizedBox(height: 15,),

                InkWell(
                    onTap: (){
                      authProvider.clearController();
                      Navigator.of(context).pushNamed(RegristrationUserRoute);   // navigation to the Registration page
                    },
                    child: Container(
                        decoration: BoxDecoration(color: Colors.deepPurple,
                            borderRadius: BorderRadius.circular(20)),
                        alignment: Alignment.center,
                        width: double.maxFinite,
                        padding: EdgeInsets.symmetric(vertical: 16),
                        child: Text(
                          "Teilnehmer werden",
                          style: TextStyle(
                            color: Colors.white,
                          ),)
                    )
                ),
              ],
            ),
          )
        ),
      ),
    );
  }
}

Github with my whole code: https://github.com/MrFunkeyfreak/stackoverflow

The form widgets looks like this, after the advice from Abdul Kadhar:

login (authentification.dart):

Form(
                  key: _formKey,
                  autovalidateMode: AutovalidateMode.always,
                  child: SingleChildScrollView(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [

                        TextFormField(
                          validator: (email) => EmailValidator.validate(email) ? null : "Bitte gib eine gültige E-Mail an.",
                          controller: authProvider.emailController,
                          keyboardType: TextInputType.text,
                          decoration: InputDecoration(
                              labelText: "E-Mail",
                              hintText: "[email protected]",
                              suffixIcon: Icon(Icons.mail_outline,),
                              isDense: true,
                              border: OutlineInputBorder(
                                  borderRadius: BorderRadius.circular(20)
                              )
                          ),
                        ),

                        SizedBox(height: 15,),

                        TextFormField(
                          validator: (password) {
                            print(authProvider.validatePassword(password));
                            return authProvider.validatePassword(password);
                          },
                          controller: authProvider.passwordController,
                          obscureText: true,
                          decoration: InputDecoration(
                              labelText: "Passwort",
                              hintText: "******",
                              suffixIcon: Icon(Icons.lock_outline, color: Colors.grey,),
                              border: OutlineInputBorder(
                                  borderRadius: BorderRadius.circular(20)
                              )
                          ),
                        ),
                      ],
                    ),
                  ),
                ),

registration.dart:

Form(
                    key: _formKey,
                    autovalidateMode: AutovalidateMode.always,
                    child: SingleChildScrollView(
                      child: Column(
                        children: [
                          TextFormField(
                            validator: (username) {
                              print(authProvider.validateUsername(username));
                              return authProvider.validateUsername(username);
                            },
                            controller: authProvider.usernameController,
                            decoration: InputDecoration(
                                labelText: "Benutzername",
                                hintText: "Max123",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(20)
                                )
                            ),
                          ),

                          SizedBox(height: 15,),

                          TextFormField(
                            validator: (email) => EmailValidator.validate(email) ? null : "Bitte gib eine gültige E-Mail an.",
                            controller: authProvider.emailController,
                            decoration: InputDecoration(
                                labelText: "E-Mail",
                                hintText: "[email protected]",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(20)
                                )
                            ),
                          ),


                          SizedBox(height: 15,),

                          TextFormField(
                            validator: (password) {
                              print(authProvider.validatePassword(password));
                              return authProvider.validatePassword(password);
                            },
                            controller: authProvider.passwordController,
                            obscureText: true,
                            decoration: InputDecoration(
                                labelText: "Passwort",
                                hintText: "******",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(20)
                                )
                            ),
                          ),


                          SizedBox(height: 15,),

                          TextFormField(
                            validator: (passwordConfirm) {
                              print(authProvider.validatePassword(passwordConfirm));
                              return authProvider.validatePassword(passwordConfirm);
                            },
                            controller: authProvider.passwordConfirmedController,
                            obscureText: true,
                            decoration: InputDecoration(
                                labelText: "Passwort wiederholen",
                                hintText: "******",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(20)
                                )
                            ),
                          ),


                          SizedBox(height: 15,),

                          TextFormField(
                            validator: (firstName) {
                              print(authProvider.validateName(firstName));
                              return authProvider.validateName(firstName);
                            },
                            controller: authProvider.firstNameController,
                            decoration: InputDecoration(
                                labelText: "Vorname",
                                hintText: "Max",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(20)
                                )
                            ),
                          ),


                          SizedBox(height: 15,),

                          TextFormField(
                            validator: (lastName) {
                              print(authProvider.validateName(lastName));
                              return authProvider.validateName(lastName);
                            },
                            controller: authProvider.lastNameController,
                            decoration: InputDecoration(
                                labelText: "Nachname",
                                hintText: "Mustermann",
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(20)
                                )
                            ),
                          ),
                        ],
                      ),
                    ),),

Error message after changing the form widgets (first I clicked on login, then on registration):

queryParameters: {} path: /login

======== Exception caught by widgets library =======================================================
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in widget tree.
====================================================================================================
queryParameters: {} path: /registrieren

======== Exception caught by widgets library =======================================================
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in widget tree.

CodePudding user response:

In your code there is a usage of separate forms for individual textfields rather you could place the the two text fields under single form widget and you could use a single globalkey(). As far as from the error message its mainly based on duplicate usage of the global please do change it the error will go away.

  • Related