skip to Main Content

I am trying to validate my form on login button press. It works perfectly fine on client side when all fields are empty however with my switch/case it does not appear to work. I believe it may be related to my validation function but I cannot pinpoint it. I believe the booleans are being set correctly in MySOAPRequest since when I press the login button then update the company or pin field the error message shows on the username field but it should show on login button press.

Login page with text fields and login button

                          CustomTextField(
                            key: _customTextFieldKey,
                            companyController: _companyController,
                            usernameController: _usernameController,
                            pinController: _pinController,
                          ),
                          const SizedBox(height: 20),
                          OutlinedButton(
                            onPressed: () {
                              FocusManager.instance.primaryFocus?.unfocus();
                              String lcomp = Globals().lcomp =
                                  _companyController.text.trim();
                              String luser = Globals().luser =
                                  _usernameController.text.trim();
                              String lpin =
                                  Globals().lpin = _pinController.text.trim();

                              if (lcomp.isNotEmpty &&
                                  luser.isNotEmpty &&
                                  lpin.isNotEmpty &&
                                  !_customTextFieldKey.currentState!
                                      .hasError()) {
                                MySOAPRequest(
                                  lcomp: lcomp,
                                  luser: luser,
                                  lpin: lpin,
                                  onLoginSuccess: _saveCredentials,
                                ).makeSOAPRequest(context);
                              } else {
                                _customTextFieldKey.currentState?.validate();
                              }
                            },
                            child: const Text('Login'),
                          ),

MySOAPRequest page code

  final String lcomp;
  final String luser;
  final String lpin;
  final Function(bool) onLoginSuccess; // define the onLoginSuccess parameter

  MySOAPRequest({
    required this.lcomp,
    required this.luser,
    required this.lpin,
    required this.onLoginSuccess,
  });

switch (logonState) {
        case '1':
          // Navigate to the Landing page if the logon state is 1
          // ignore: use_build_context_synchronously
          loginFlushbar(context);
          // ignore: use_build_context_synchronously
          navigateToSubPages(context);
          onLoginSuccess(true);
          break;
        case '3':
          // ignore: use_build_context_synchronously
          flushbar(context, 'Incorrect User Name',
              'Please try again or contact your administrator if this issue persists.');
          onLoginSuccess(false);
          break;
            default:
          // ignore: use_build_context_synchronously
          flushbar(context, 'Unknown Error',
              'An unknown error occurred. Please try again or contact your administrator.');
              Globals().usernameHasError = true;
          Globals().errorText = 'Incorrect User Name';
          Globals().customTextFieldKey.currentState?.validate();
          onLoginSuccess(false);
          break;
      }

Username field text

class CustomTextFieldState extends State<CustomTextField> {
  final _formKey = GlobalKey<FormState>();
  //final _usernameKey = Globals().customTextFieldKey;

  String _company = '';
  String _username = '';
  String _pin = '';

  bool _companyHasError = false;
  bool _usernameHasError = false;
  bool _pinHasError = false;

  bool hasError() {
    return _usernameHasError || _companyHasError || _pinHasError;
  }

  void validate() {
    setState(() {
      if (_formKey.currentState != null) {
        _companyHasError =
            !_formKey.currentState!.validate() || _company.isEmpty;
        _usernameHasError =
            !_formKey.currentState!.validate() || _username.isEmpty;
        _pinHasError = !_formKey.currentState!.validate() || _pin.isEmpty;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    String lcomp = widget.companyController.text.trim();

    return Form(
      key: _formKey,
      autovalidateMode: AutovalidateMode.disabled,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          Padding(
            padding: const EdgeInsets.only(bottom: 20.0),
            //!--- COMPANY TEXT FIELD --- //

            child: TextFormField(
              controller: widget.companyController,
              decoration: InputDecoration(
                contentPadding: const EdgeInsets.only(left: 20),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30),
                  borderSide: const BorderSide(
                    color: Color(0xff185C91),
                  ),
                ),
                focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30),
                  borderSide: const BorderSide(
                    color: ThemeClass.primaryColor,
                  ),
                ),
                enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30),
                  borderSide: const BorderSide(
                    color: Color(0xff185C91),
                  ),
                ),
                errorBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30),
                  borderSide: const BorderSide(color: Colors.red),
                ),
                disabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(30),
                  borderSide: const BorderSide(color: Color(0x00232323)),
                ),
                suffixIcon: const Icon(Icons.corporate_fare_outlined,
                    color: ThemeClass.primaryColor),
                labelText: "Company Name",
                labelStyle: const TextStyle(
                  fontSize: 14.0,
                  decoration: TextDecoration.none,
                ),
                hintText: 'Enter Company Name',
                hintStyle: const TextStyle(
                  fontSize: 14.0,
                ),
                errorText: _companyHasError
                    ? 'Please enter a valid company name!'
                    : ((_company.isNotEmpty &&
                            !Globals().resultList.contains(lcomp))
                        ? 'Please enter a valid company name!'
                        : null),
              ),
              autovalidateMode: AutovalidateMode.onUserInteraction,
              validator: (value) {
                if (value == null || value.isEmpty) {
                  return 'Please enter your company name!';
                }
                return null;
              },
              onChanged: (value) {
                setState(() {
                  _company = value;
                  _companyHasError = false;
                });
              },
              onFieldSubmitted: (value) {
                setState(() {
                  _companyHasError = !_formKey.currentState!.validate();
                });
              },
            ),
          ),
          //!--- END COMPANY TEXT FIELD --- //

          //!--- USERNAME TEXT FIELD --- //
          TextFormField(
            controller: widget.usernameController,
            //key: _usernameKey,
            decoration: InputDecoration(
              contentPadding: const EdgeInsets.only(left: 20),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(
                  color: Color(0xff185C91),
                ),
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(
                  color: ThemeClass.primaryColor,
                ),
              ),
              enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(
                  color: Color(0xff185C91),
                ),
              ),
              errorBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(color: Colors.red),
              ),
              disabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(color: Color(0x00232323)),
              ),
              suffixIcon: const Icon(Icons.person_outlined,
                  color: ThemeClass.primaryColor),
              labelText: "Username",
              labelStyle: const TextStyle(
                fontSize: 14.0,
                decoration: TextDecoration.none,
              ),
              hintText: 'Enter username',
              hintStyle: const TextStyle(
                fontSize: 14.0,
              ),
              errorText: _usernameHasError
                  ? 'Please enter a valid username!'
                  : Globals().usernameHasError
                      ? Globals().errorText
                      : null,
            ),
            autovalidateMode: AutovalidateMode.onUserInteraction,
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter your username!';
              }
              return null;
            },
            onChanged: (value) {
              setState(() {
                _username = value;
                _usernameHasError = false;
                Globals().usernameHasError = false;
              });
            },
            onFieldSubmitted: (value) {
              setState(() {
                _usernameHasError = !_formKey.currentState!.validate();
              });
            },
          ),
          //!--- END USERNAME TEXT FIELD --- //

          const SizedBox(height: 20),

          //!--- PIN TEXT FIELD --- //
          TextFormField(
            controller: widget.pinController,
            inputFormatters: [
              LengthLimitingTextInputFormatter(6),
              FilteringTextInputFormatter.digitsOnly
            ],
            obscureText: true,
            keyboardType: TextInputType.number,
            decoration: InputDecoration(
              contentPadding: const EdgeInsets.only(left: 20),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(
                  color: Color(0xff185C91),
                ),
              ),
              focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(
                  color: ThemeClass.primaryColor,
                ),
              ),
              enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(
                  color: Color(0xff185C91),
                ),
              ),
              errorBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(color: Colors.red),
              ),
              disabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: const BorderSide(color: Color(0x00232323)),
              ),
              suffixIcon: const Icon(Icons.pin_outlined,
                  color: ThemeClass.primaryColor),
              labelText: "PIN",
              labelStyle: const TextStyle(
                fontSize: 14.0,
                decoration: TextDecoration.none,
              ),
              hintText: 'Enter PIN',
              hintStyle: const TextStyle(
                fontSize: 14.0,
              ),
              errorText: _pinHasError
                  ? 'Please enter a valid PIN!'
                  : _pin.length < 4 && _pin.isNotEmpty
                      ? 'PIN is too short!'
                      : null,
            ),
            autovalidateMode: AutovalidateMode.onUserInteraction,
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter your PIN!';
              }
              return null;
            },
            onChanged: (value) {
              setState(() {
                _pin = value;
                _pinHasError = false;
              });
            },
            onFieldSubmitted: (value) {
              setState(() {
                _pinHasError = !_formKey.currentState!.validate();
              });
            },
          ),
          //!--- END PIN TEXT FIELD --- //
        ],
      ),
    );
  }
}

2

Answers


  1. i just saw something bad you are doing on the switch case,

      ignore: use_build_context_synchronously
    

    there is a reason why you should not call the build context asynchronously, it may have been unmounted since you passed it aroud

    if you are using a stateful widget, which appears to be so, you can define your context dependendant functions outside the build widget like this

     StatefulWidget{
    
     void _loginFlushBar() => loginFlushbar(context);
     void _navigateToSubPages => navigateToSubPages(context);
    
    
    
       Widget build(Buildcontext context){
          //Your widgets
       }
    
    }
    
    Login or Signup to reply.
  2. Wrap your TextFormField in a Form widget and provide a GlobalKey<FormState> to the Form as its key. Then you can validate it with _formKey.currentState!.validate().

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search