validationfluttertextfield

How to put global key _keyForm inside my TextFormField as it is separated by different widget


I am trying to figure out how to put my global _formKey inside my form field as it is separated by different widget. I try putting they key in both widget, but it detected as 2 different widget is using the same global key. This is my code which i have trying to fix. I hope i can get some help with this form validation. Thank you.

  final AuthService _auth = AuthService();
  final _formKey = GlobalKey<FormState>();

  //text field state
  String username = '';
  String password = '';
  String error ='';

  bool _rememberMe = false;

  Widget _buildUsernameTF() {
   return Column(
    crossAxisAlignment: CrossAxisAlignment.start,
     children: <Widget>[
      Text(
       'Username',
         style: kLabelStyle,
       ),
    SizedBox(height: 10.0),
    Container(
      alignment: Alignment.centerLeft,
      decoration: kBoxDecorationStyle,
      height: 60.0,
        child: TextFormField(
        validator: (val) => val.isEmpty ? 'Enter the username' : null,
        onChanged: (val){
          setState(() => username = val);
        }, 
        keyboardType: TextInputType.emailAddress,
        style: TextStyle(
          color: Colors.white,
          fontFamily: 'OpenSans',
        ),
        decoration: InputDecoration(
          border: InputBorder.none,
          contentPadding: EdgeInsets.only(top: 14.0),
          prefixIcon: Icon(
            Icons.person,
            color: Colors.white,
          ),
          hintText: 'Enter your username',
          hintStyle: kHintTextStyle,
        ),
      ),
    ),
  ],
);}

  Widget _buildPasswordTF() {
  return Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: <Widget>[
    Text(
      'Password',
      style: kLabelStyle,
    ),
    SizedBox(height: 10.0),
    Container(
      alignment: Alignment.centerLeft,
      decoration: kBoxDecorationStyle,
      height: 60.0,
      child: TextFormField(
        validator: (val) => val.length < 8 ? 'Enter the password at least 8 chars long' : null,
        onChanged: (val){
          setState(() => password = val);
        },
        obscureText: true,
        style: TextStyle(
          color: Colors.white,
          fontFamily: 'OpenSans',
        ),
        decoration: InputDecoration(
          border: InputBorder.none,
          contentPadding: EdgeInsets.only(top: 14.0),
          prefixIcon: Icon(
            Icons.lock,
            color: Colors.white,
          ),
          hintText: 'Enter your Password',
          hintStyle: kHintTextStyle,
        ),
      ),
    ),
  ],
);
}

Solution

  • FormKey is used for a single Form() only. Please read about Form Field Validation here. The use case is this, that Form class should be having only single _formKey and the all the TextFields() will be mentioned in the child of the Form. Please see the representation

    final _formKey = GlobalKey<FormState>();
    
    Form(
      key: _formKey,
      // Here you can get your child/children on the basis of your requirements
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
            //Mention both of your TextFields here
        ]
      )
    )
    

    So your code should be like this, to be workable.

    final _formKey = GlobalKey<FormState>();
    
    Form(
      key: _formKey,
      // Here you can get your child/children on the basis of your requirements
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
            _buildUsernameTF(),
            _buildPasswordTF()
        ]
      )
    )