TextFormField validator not working - The method 'validate' was called on null
Solution 1
You didn't add the key
to the form, this code should work:
class _LoginForm extends State<LoginForm> {
// GlobalKey<FormState> formKey = GlobalKey();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _email;
String _password;
void validateAndSave() {
final FormState form = _formKey.currentState;
if (form.validate()) {
print('Form is valid');
} else {
print('Form is invalid');
}
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(left: 15.0, right: 15.0),
child: Form(
key: _formKey,
child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(
height: 150.0,
),
// input field for email
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) =>
value.isEmpty ? 'Email cannot be blank' : null,
// onSaved: (value) => _email = value,
),
// input field for password
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) =>
value.isEmpty ? 'Password cannot be blank' : null,
// onSaved: (value) => _password = value,
),
RaisedButton(
child: Text(
'Login',
style: TextStyle(fontSize: 20.0),
),
onPressed: validateAndSave,
),
],
),
),
);
}
}
Solution 2
If someone have the same error even adding the key and your structure is:
Form => ListView => [TextFormField(s)],
try to change the structure:
Form => SingleScrollView => Column
This change worked for me.
Happy coding.
Solution 3
The question was already solved, but if it's still not working after adding the key and changing the structure to one of the following:
Form => SingleChildScrollView => Column => [TextFormField(s)],
or
SingleChildScrollView => Form => Column => [TextFormField(s)],
Try adding:
autovalidateMode: AutovalidateMode.onUserInteraction
For example:
TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.person),
labelText: 'User:',
),
onSaved: (){},
autovalidateMode:
AutovalidateMode.onUserInteraction,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your user name.';
} else if (value.contains('@')) {
return 'Please don\'t use the @ char.';
}
return null;
},
textInputAction: TextInputAction.next,
),
Santhosh Jose
Specialties Bacon Number: 3 Experienced at Loading and Un-loading....weights.
Updated on July 05, 2022Comments
-
Santhosh Jose almost 2 years
I am trying to build a simple login page for a new flutter app. The widget tree is very basic. It consists of a MaterialApp that contains a Scaffold. The 'home' of the Scaffold is a StatefulWidget which contains the Form with two TextFormFields inside.
The TextFormFields have 'validator' code to check for null values.
There is a button which invokes a method 'validateAndSave' when pressed. Inside this method, I am calling 'validate' method for an instance of the GlobalKey.
When clicking on the button, the validators don't seem to be firing and I am getting the following error message:
I/flutter (10459): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════ I/flutter (10459): The following NoSuchMethodError was thrown while handling a gesture: I/flutter (10459): The method 'validate' was called on null. I/flutter (10459): Receiver: null I/flutter (10459): Tried calling: validate() I/flutter (10459): I/flutter (10459): When the exception was thrown, this was the stack: I/flutter (10459): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5) I/flutter (10459): #1 _LoginForm.validateAndSave (package:playground/main.dart:33:13)
I tried running flutter clean on the project and re-running the application. I still get the error message.
Here is the code that I am running.
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Playground', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold(body:LoginForm() ), ); } } class LoginForm extends StatefulWidget { @override State<StatefulWidget> createState() => _LoginForm(); } class _LoginForm extends State<LoginForm>{ // GlobalKey<FormState> formKey = new GlobalKey(); final _formKey = new GlobalKey<FormState>(); String _email; String _password; void validateAndSave(){ final form = _formKey.currentState; if(form.validate()) { print ('Form is valid'); } else { print('form is invalid'); } } @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.only(left: 15.0, right: 15.0), child: Form( child: Column( // mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ SizedBox(height: 150.0,), //input field for email TextFormField( decoration: InputDecoration(labelText: 'Email'), validator: (value) => value.isEmpty ? 'Email cannot be blank':null, // onSaved: (value) => _email = value, ), //input field for password TextFormField( decoration: InputDecoration(labelText: 'Password'), obscureText: true, validator: (value) => value.isEmpty ? 'Password cannot be blank':null, // onSaved: (value) => _password = value, ), RaisedButton( child: Text ('Login', style: TextStyle(fontSize: 20.0),), onPressed: validateAndSave, ) ] ) ) ); } }
I feel like I have missed something in the code. I would appreciate any help in sorting this issue out.
-
Fellow7000 over 3 yearsThanks a lot! This saved a lot of time today! :)
-
Eradicatore about 3 yearsThis is an awesome example of how to validate AFTER you click submit, so it doesn't show red while you type in the email.
-
Soorya almost 3 years@Pedro Molina can you give more explanation why this is happening?