Reputation: 1092
I am experimenting with flutter and I am stucked with a silly problem. I have defined two TextInputField in a screen, and I am validating using Form. Everything is working fine, my only problem, error is not going away even after values which is inserted are fine.
Below is the screenshot before entering the value. Error is showing at the start of the screen as well.
Below is the screen after entering the value. When i click on signup button, error is still showing.
You can see, value is getting printed in logs when i click on Sign Up button.
Widget Class
class SignUpForm extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return SignUpState();
}
}
State Class
class SignUpState extends State<SignUpForm> {
final _fbKey = GlobalKey<FormState>();
final UserDetails userDetails = UserDetails();
bool _autoValidate = true;
@override
Widget build(BuildContext context) {
return CustomScreenBg(
AppString.additional_information,
CustomCard(_getSignUpForm(context)),
);
}
_getSignUpForm(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(12),
child: Form(
key: _fbKey,
autovalidate: _autoValidate,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
RichText(
text: TextSpan(
text: AppString.welcome_to,
style: TextStyle(
color: AppColor.BLACK.toColor,
fontSize: 18,
),
children: <TextSpan>[
TextSpan(
text: '${AppString.app_name}',
style: TextStyle(
fontSize: 24,
color: AppColor.PRIMARY_COLOR.toColor,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SubTitleText(AppString.lets_get_started),
],
),
SizedBox(height: 16),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: AppString.enter_name,
errorText: AppString.error_name,
),
keyboardType: TextInputType.text,
validator: (value) {
if (value.length < 4) {
return AppString.error_name;
}
return null;
},
onSaved: (name) {
userDetails.name = name;
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
labelText: AppString.enter_email,
errorText: AppString.error_email,
),
keyboardType: TextInputType.text,
validator: (value) {
if (value.length < 5 || !value.contains('@')) {
return AppString.error_email;
}
return null;
},
onSaved: (email) {
userDetails.email = email;
},
),
],
),
SizedBox(height: 24),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
CustomButton(
AppString.sign_up,
() {
_onSubmit();
},
textColor: AppColor.WHITE.toColor,
bgColor: AppColor.PRIMARY_COLOR.toColor,
),
],
),
SizedBox(height: 12)
],
),
),
);
}
_onSubmit() {
if (_fbKey.currentState.validate()) {
_fbKey.currentState.save();
print(userDetails.name);
print(userDetails.email);
} else {
setState(() {
_autoValidate = true;
});
}
}
}
This method is getting called when clicking on Sign Up Button.
_onSubmit() {
if (_fbKey.currentState.validate()) {
_fbKey.currentState.save();
print(userDetails.name);
print(userDetails.email);
} else {
setState(() {
_autoValidate = true;
});
}
}
Can someone help me in figuring it out, what i am doing wrong?
Upvotes: 6
Views: 17985
Reputation: 1
Just need to add this line to your Form widget.
autovalidateMode: AutovalidateMode.onUserInteraction,
This autovalidateMode: AutovalidateMode.onUserInteraction, will validate automatically.
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: TextField(),
)
Upvotes: 0
Reputation: 941
TextFormFiled has a new property since v1.19, called autovalidateMode
. It provides multiple modes, but I think thast AutovalidateMode.onUserInteraction
works best. It only autovalidate the Form after each user interaction.
Upvotes: 4
Reputation: 107121
You don't have to set the errorText
property, when validation fails it will show the message returned by the validator callback. So for fixing the issue, all you want is to remove errorText
from your TextFormField.
Upvotes: 2
Reputation: 1784
In my experience it is better to control the autoValidate property yourself. So following an example from here
First set class Boolean variable :
bool _autovalidate = false;
Then pass it to your form:
Form(
key: _fbKey,
autovalidate: _autovalidate,
...
)
Then in your validator:
validator: (value) {
if (value.length < 5 || !value.contains('@')) {
return AppString.error_email;
setState(() => _autoValidate = true);
}
return null;
}
Upvotes: 4