Zerocchi
Zerocchi

Reputation: 632

Validator pushed TextFormField above

I tried creating an email textfield with validator using TextFormField. Since the textfield height is too much for my liking, I wrap the TextFormField with Container and set the height to 50. Now the problem is whenever I submitted intended wrong value, the validator will popped out and pushed the textfield, leaving the height much smaller than what I set in Container.

Before submitting:

Before submitting

After submitting:

enter image description here

Here is my codes:

Widget _emailForm() {
    return Form(
      key: _emailFormKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Text("Enter Your Email", style: TextStyle(fontSize: 13.0, fontWeight: FontWeight.bold),),
          Padding(padding: EdgeInsets.symmetric(vertical: 4.0),),
          Container(
            height: 50,
            child: TextFormField(
              focusNode: _emailFocusNode,
              style: TextStyle(fontSize: 11.0, fontWeight: FontWeight.w600),
              keyboardType: TextInputType.emailAddress,
              controller: _emailTextController,
              decoration: InputDecoration(
                isDense: true,
                focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.all(Radius.circular(0.0),),
                ),
                suffixIcon: IconButton(
                  alignment: Alignment.centerRight,
                  iconSize: 16.0,
                  icon: Icon(Icons.clear),
                  onPressed: () {
                    if(_emailTextController != null) {
                        _emailTextController.clear();
                        FocusScope.of(context).requestFocus(_emailFocusNode);
                    }
                  },
                ),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.all(
                    Radius.circular(0.0),
                  ),
                  borderSide: BorderSide(
                    color: Colors.black,
                    width: 1.0
                  )
                ),
                errorStyle: _errorTextStyle,
              ),
              validator: (val) {
                Pattern pattern = r'@';
                RegExp regex = RegExp(pattern);
                if(val.isEmpty) return "* Email address can't be empty";
                else if(!regex.hasMatch(val)) return "* Invalid email address";
                else {
                  return null;
                }
              },
            ),
          ),
          Padding(padding: EdgeInsets.symmetric(vertical: 6.0),),
          FlatButton(
            child: Text("Join".toUpperCase(), style: TextStyle(color: Colors.white, fontSize: 11),),
            onPressed: (){
              if(_emailFormKey.currentState.validate()) {
                _joinWaitingList();
              }
            },
            color: _themeColor,
          ),
        ],
      ),
    );
  }

This widget is part of ListView in my build method if that information is helping. Is there any way to solve this problem? Thanks!

Upvotes: 9

Views: 7266

Answers (2)

Justin McCandless
Justin McCandless

Reputation: 671

The problem is that TextField and TextFormField size themselves to include all of their content and decoration. If you add some error text onto the bottom of the TextFormField, then it will include that in its height. When it tries to size itself to fit into your Container, it doesn't have as much space for the input.

You could work around this by specifying the height of your Container in both the valid and invalid states. You'll have to fiddle with the exact invalid height, but it might look something like this:

Container(
  height: _isInvalid ? 100 : 50,
  TextFormField(),
),

Another option is to add counterText: ' ' to your InputDecoration and then size the Container to the size that you want. This will give you extra space to fit the error text without needing to change the height of the TextFormField.

Container(
  height: 100,
  TextFormField(
    decoration: InputDecoration(
      counterText: ' ',
    ),
  ),
),

The cleanest solution, if it's possible for you, may be to not use a Container at all. If you can create the input you want just by using InputDecoration and things like contentPadding etc., it will likely make this a lot cleaner.

Upvotes: 11

GirlWhoCode
GirlWhoCode

Reputation: 628

hey i think that its works if u use onchanged instead of validator :

 onChanged: (val) {
                Pattern pattern = r'@';
                RegExp regex = RegExp(pattern);
                if(val.isEmpty) return "* Email address can't be empty";
                else if(!regex.hasMatch(val)) return "* Invalid email address";
                else {
                  return null;
                }
              },

Upvotes: 1

Related Questions