CodeGeek
CodeGeek

Reputation: 721

Custom Validation TextFormField Flutter

I have Form and TextFormField inside it :

 new Expanded(
  child: TextFormField(
    style: new TextStyle(color: Colors.white),
    keyboardType: TextInputType.text,
    validator: (String value) {
      if (value.length <= 5) {
       //Show error as a Snackbar
      }
    },
    onSaved: (String value) {},

  ),
)

On a Buttom press I am checking if all the fields are validate :

 if (_formKey.currentState.validate()) {
      _submit();
 }

Now the issue is when you call validate() and don't return any text in validate() method then it will consider it return true.

I don't want to show error below the textField but as a Snackbar.

Also, I tried setting an extra flag and setting in each validator Method but it gets complex if there are multiple fields in the form.

Can anyone tell me how can I handle this situation where _formKey.currentState.validate() should return false and validator method inside TextFormField need not to return error text.

Upvotes: 4

Views: 18924

Answers (2)

O&#39;Prime
O&#39;Prime

Reputation: 101

I see that you want to validate the user-input in multiple form-fields but you don't want to display the error message below the form-field if the validation fails.

Firstly, the _formKey.currentState.validate() method validates every TextFormField wrapped as children within a Form widget as parent with _formKey as GlobaKey attached to it.

Secondly, validate() method returns true only if user-input passes all the conditions specified in the validator property for the respective form-field and returns false if any of them fails to satisfy.

With these two points in mind, it would be contradicting when we ask flutter to validate the form-field and to return false upon successful validation.

The solution for your 1st problem lies in the fact that the framework calls the [onSaved()][1] callack when it encounters _formKey.currentState.save(). So, if you want to show a snackBar upon successful validation, write your logic within the onSaved() property.

As for the 2nd problem, you can just over-ride the errorText, errorStyle, and errorBorder properties in the decoration property of your TextFormField as per your requirements. For more info on this one refer to this answer: https://stackoverflow.com/a/76739149/19368196.

 new Expanded(
     child: TextFormField(
     style: new TextStyle(color: Colors.white),
     keyboardType: TextInputType.text,
     decoration: InputDecoration(
     // Override the errorText and errorBorder as per your requirement.
       errorText: "",
       errorBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.transparent),
      ),
     ),
     validator: (String value) {
      if (value.length <= 5) {
       // Just leave it empty as you don't wanna show any error text.
      }
     },
    onSaved: (String value) {
         // Show snackbar
        },
      ),
    )

On button press,

 if (_formKey.currentState.validate()) {
  _formKey.currentState.save();
 }

Hope this was helpful.

Upvotes: 1

Nikhil Vadoliya
Nikhil Vadoliya

Reputation: 1588

You shouldn't be using Form widget and TextFormField for displaying error in TextField.

Do validation by controllers instead

For Example

class MyHomePage extends StatefulWidget {
  @override
  MyHomePageState createState() {
    return new MyHomePageState();
  }
}

class MyHomePageState extends State<MyHomePage> {
  final _text = TextEditingController();
  bool _validate = false;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TextField Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Error Showed if Field is Empty on Submit button Pressed'),
            TextField(
              controller: _text,
              decoration: InputDecoration(
                labelText: 'Enter the Value',
              ),
            ),
            RaisedButton(
              onPressed: () {
                        if(_text.text.length<=5){
                    // open dialog
                  }
              },
              child: Text('Submit'),
              textColor: Colors.white,
              color: Colors.blueAccent,
            )
          ],
        ),
      ),
    );
  }
}

Upvotes: 3

Related Questions