Flutter form button enabled not updating after fields validation - forms

I am still learning Flutter and scratching my head around this.
I have a form with 3 fields (email, password and password_confirmation).
I am using validators and updating a variable that is used as a condition on the button enabled state.
The problem is that the button enabled state is not being updated when I change for instance the email...
If I hot restart, it will update the button state..
How can I force the button to reevaluate it's condition?
What is the Flutter way of doing this?
Thank you
bool _validEmail = false;
bool _validPassword = false;
bool _validPasswordConfirmation = false;
bool _validAccount = false;
SignUpError _serverSignUpErrors = null;
Form signup_form() {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//Email field
Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Email",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
SizedBox(
height: 10,
),
TextFormField(
controller: _emailFieldController,
obscureText: false,
decoration: InputDecoration(
border: InputBorder.none,
fillColor: Color(0xfff3f3f4),
filled: true),
onChanged: (String value) {
if(_serverSignUpErrors?.email_errors?.isNotEmpty == true)
_serverSignUpErrors.email_errors.clear();
},
autovalidate: true,
validator: (value) {
_validEmail = false;
if (value.isEmpty)
return 'Please enter some text';
//Validate email
String p = r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(p);
if(!regExp.hasMatch(value))
return 'Invalid email';
if(_serverSignUpErrors?.email_errors?.isNotEmpty == true)
return _serverSignUpErrors.email_errors.join(';');
_validEmail = true;
return null;
}
)
],
),
),
//Password field
Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Password",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
SizedBox(
height: 10,
),
TextFormField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(
border: InputBorder.none,
fillColor: Color(0xfff3f3f4),
filled: true),
onChanged: (String value) {
if(_serverSignUpErrors?.password_errors?.isNotEmpty == true)
_serverSignUpErrors.password_errors.clear();
this.didChangeDependencies();
},
autovalidate: true,
validator: (value) {
_validPassword = false;
if (value.isEmpty || value.length < 4)
return 'Password must be at least 6 chars wide';
if(_serverSignUpErrors?.password_errors?.isNotEmpty == true)
return _serverSignUpErrors.password_errors.join(';');
_validPassword = true;
return null;
}
)
],
),
),
//Password field
Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Password confirmation",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
SizedBox(
height: 10,
),
TextFormField(
controller: _passwordConfirmationController,
obscureText: true,
decoration: InputDecoration(
border: InputBorder.none,
fillColor: Color(0xfff3f3f4),
filled: true),
onChanged: (String value) {
if(_serverSignUpErrors?.password_confirmation_errors?.isNotEmpty == true)
_serverSignUpErrors.password_confirmation_errors.clear();
this.didChangeDependencies();
},
autovalidate: true,
validator: (value) {
_validPasswordConfirmation = false;
if (value.isEmpty)
return 'Please enter password confirmation';
if(value != _passwordController.text)
return 'Password confirmation doesn\'t match password';
if(_serverSignUpErrors?.password_confirmation_errors?.isNotEmpty == true)
return _serverSignUpErrors.password_confirmation_errors.join(';');
_validPasswordConfirmation = true;
return null;
}
)
],
),
),
Center(
child: FlatButton(
onPressed: (_validEmail && _validPassword && _validPasswordConfirmation && _validAccount == false) ? () async => await onRegister() : null,
disabledColor: Colors.blueGrey,
child: Text(
'Register Now',
style: TextStyle(fontSize: 20, color: Colors.white),
),
color: Colors.blue, //specify background color for the button here
colorBrightness: Brightness.dark, //specify the color brightness here, either `Brightness.dark` for darl and `Brightness.light` for light
highlightColor: Colors.red, //color when the button is being actively pressed, quickly fills the button and fades out after
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 5.0), // gives padding to the button
),
),
]
)
);
}

It seems you're == false is reversing your intended behavior. Not sure if that's what you want.
onPressed: (_validEmail && _validPassword && _validPasswordConfirmation && _validAccount == false) ? () async => await onRegister() : null,
To solve your error you should wrap anything where you change the state with variables like _validEmail, _validPassword, etc. with setState(() {});. This will rebuild the widget, including the button, when you change the state so it will enable when you want and you'll get the behavior you want.

Related

I do all possible to solve that error Null check operator used on a null value I use (!) but there is error

class login extends StatelessWidget {
var emailController = TextEditingController();
var PasswordController = TextEditingController();
var _formKey = GlobalKey<FormState>();
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Login"),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Center(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Login",
style: TextStyle(
fontSize: 40, fontWeight: FontWeight.bold)),
SizedBox(height: 40,),
TextFormField(
controller: emailController,
onFieldSubmitted: (String value) {
print(value);
},
onChanged: (String value) {
print(value);
},
validator: (String ?value) {
if (value == null || value.isEmpty) {
return 'the password must not be Empty';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: "E-mail Address",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
prefixIcon: Icon(Icons.email),
),
),
SizedBox(height: 20,),
TextFormField(
controller: PasswordController,
obscureText: true,
keyboardType: TextInputType.visiblePassword,
validator: (String ?value) {
if (value == null || value.isEmpty) {
return 'the password must not be Empty';
}
return null;
},
onFieldSubmitted: (String value) {
print(value);
},
onChanged: (String value) {
print(value);
},
decoration: InputDecoration(
labelText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
prefixIcon: Icon(Icons.lock),
suffixIcon: Icon(Icons.remove_red_eye_rounded)
)
),
SizedBox(height: 20,),
defaultButton(
background: Colors.black26,
isUpperCase: true,
text: "Login",
function: () {
if (_formKey.currentState!.validate()) ==> // Null check operator
used on a null value.
{
print(emailController);
print(PasswordController);
}
}
),
SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Already you Have account?"),
TextButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) => Registry()));
},
child: Text("Register now "))
],
),
],
),
),
),
),
),
);
}
}
Hey what you're using is called the non-null assertion operator, it actually means you are saying that value can't be null. If you want to make sure it's not null before trying to access validate(), you should use optional chaining _formKey.currentState?.validate()
What you can also try to do is check that it's not null before you call validate().
if (!!_formkey.currentState && _formKey.currentState.validate())

Conditional statement for DropdownButtonFormFields in registeration form

Still a newbie with flutter and was wondering if someone could help me with a problem I'm having. I am trying to create a registeration form with email, password, password confirmation, a county and a zip code. (County and zip code forms are the drop down button form fields) I have successfully coded all else except for the zip code drop down. I would need it to be conditional on the county selection. (In a way that if I select a specific county in cali, it would only display that selected county's zip codes and nothing else). Also if someone would know a quick fix to make the dropdown button form fields empty unless clicked on. My current adaptation on it isn't very functional, since you can just leave the option unanswered, when it's supposed to be mandatory. Thank you in advance :)
Existing code below
(I only have the string for one county zip codes) (Also deleted the irrelevant firebase related code for this post)
class RegisterPage extends StatefulWidget {
const RegisterPage({Key? key}) : super(key: key);
#override
State<RegisterPage> createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
// dropdown area
_MyFormStateArea(){
selectedArea = dropdownListArea[0];
}
var selectedArea = '';
final dropdownListArea = <String>['', 'LA', 'San Francisco'...'Santa Barbara'];
// dropdown zipcode
_MyFormStateZip(){
selectedZip = dropdownListZip[0];
}
var selectedZip = '';
final dropdownListZip = <String>['', '90001', '90002', '90003',..., '91609'];
// editing Controller
final emailEditingController = new TextEditingController();
final passwordEditingController = new TextEditingController();
final confirmPasswordEditingController = new TextEditingController();
#override
Widget build(BuildContext context) {
// email field
final emailField = TextFormField(
autofocus: false,
controller: emailEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty) {
return ("Please enter email.");
}
// reg expression for email validation
if (!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]")
.hasMatch(value)) {
return ("Please enter a working email.");
}
return null;
},
onSaved: (value) {
emailEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.mail_outline_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)
),
),
);
// password field
final passwordField = TextFormField(
autofocus: false,
controller: passwordEditingController,
obscureText: true,
validator: (value) {
RegExp regex = new RegExp(r'^.{6,}$');
if (value!.isEmpty) {
return ("A password required.");
}
if(!regex.hasMatch(value)) {
return ("Please enter other password (Min. 6 characters)");
}
},
onSaved: (value) {
passwordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
));
// confirm password field
final confirmPasswordField = TextFormField(
autofocus: false,
controller: confirmPasswordEditingController,
obscureText: true,
validator: (value)
{
if(confirmPasswordEditingController.text != passwordEditingController.text)
{
return "Passwords don't match";
}
return null;
},
onSaved: (value) {
confirmPasswordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password again",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)
),
),
);
// area dropdown
final areaField = DropdownButtonFormField(
value: selectedArea,
items: dropdownListArea.map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedArea = value;
}
});
},
decoration: InputDecoration(
labelText: 'County',
prefixIcon: Icon(Icons.location_city_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);
// zip code field
final zipCodeField = DropdownButtonFormField(
value: selectedZip,
items: dropdownListZip.map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedZip = value;
}
});
},
decoration: InputDecoration(
labelText: 'Zip Code',
prefixIcon: Icon(Icons.location_on_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);
// sign up button
final signUpButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(30),
color: Colors.white,
child: MaterialButton(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signUp(emailEditingController.text, passwordEditingController.text);
},
child: Text("Sign Up", textAlign: TextAlign.center,
style: TextStyle(fontSize: 20,
color: Colors.lightBlue[900],
fontWeight: FontWeight.bold)
),
),
);
return Scaffold(
backgroundColor: Color(0xFFAED8E6),
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => FrontPage()));
},
icon: Icon(Icons.arrow_back),
color: Colors.lightBlue[900],
),
),
body: Center(
child: SingleChildScrollView(
child: Container(
color: Color(0xFFAED8E6),
child: Padding(
padding: const EdgeInsets.fromLTRB(36, 20, 36, 30),
child: Form(
key: _formKey,
child:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 170,
child: Image.asset("assets/AR_logoBold.png",
fit: BoxFit.contain
)),
SizedBox(height: 40,),
emailField,
SizedBox(height: 25,),
passwordField,
SizedBox(height: 25,),
confirmPasswordField,
SizedBox(height: 25,),
areaField,
SizedBox(height: 25,),
zipCodeField,
SizedBox(height: 35,),
signUpButton,
SizedBox(height: 15,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("You already own an account? "),
GestureDetector(onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => LoginPage()));
},
child: Text("Login",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Colors.lightBlue[900])
),)
],
)
],
)),
),
),
),
),
);
}
}
First you should initalize the selectedArea and selectedZip with the first Entry of your List: = dropdownListZip.first and the first entry should not be an empty String
To get only zips that belong to the choosen area you need to know them. At the moment you have two independent lists.
Better you use a map like:
Map<String, List<String>> zipmap = Map('LA': ['9000','9001','9002], 'San Francisco': ['9003', '9004']);
Than you can only display zips that belong to the area quite easy.
Take a look at: Flutter Documentation for Map
Map<String, List<String>> zipmap = Map('LA': ['9000','9001','9002], 'San Francisco': ['9003', '9004']);
final areaField = DropdownButtonFormField(
value: selectedArea,
items: zipmap.keys.toList().map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedArea = value;
}
});
},
decoration: InputDecoration(
labelText: 'County',
prefixIcon: Icon(Icons.location_city_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);
// zip code field
final zipCodeField = DropdownButtonFormField(
value: selectedZip,
items: zipmap[selectedArea].map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedZip = value;
}
});
},
decoration: InputDecoration(
labelText: 'Zip Code',
prefixIcon: Icon(Icons.location_on_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);

Validating TextformField with two different key in Flutter

I'm trying to validate two different TextFormFields in two widgets (One for Email, another one for password) with a single _formkey in a flutter. it gave me this error: Multiple widgets used the same GlobalKey. So defined two _formkey but the problem is Flutter form validators don't validate, simultaneously:
class _RegisterState extends State<Register> {
String email = "";
String password = "";
String error = "";
final _formKey1 = GlobalKey<FormState>();
final _formKey2 = GlobalKey<FormState>();
// bool _rememberMe = false;
Widget _buildEmailTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Email',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Form(
key: _formKey1,
child: Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
validator: (value) => value.isEmpty ? "Enter an Email" : null,
onChanged: (value) {
setState(() {
email = value;
});
},
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Enter your Email',
hintStyle: kHintTextStyle,
),
),
),
),
],
);
}
Widget _buildPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Form(
key: _formKey2,
child: Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
validator: (value) =>
value.length < 6 ? "More than 6 Character" : null,
onChanged: (value) {
setState(() {
password = value;
});
},
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,
),
),
),
),
],
);
}
and then :
onPressed: () async {
if (_formKey1.currentState.validate() &&
_formKey2.currentState.validate()) {
dynamic result =
await _auth.signUpWithEmailandPassword(email, password);
if (result == null) {
setState(() => error = "Something is wrong");
}
}
},
Just remember that you need one Form Widget above in the widget Tree.
And thus you can use the _formKey to validate multiple TextFormField below in the Widget Tree.
Modified Code
class _RegisterPageState extends State<RegisterPage> {
String email = "";
String password = "";
String error = "";
final _formKey1 = GlobalKey<FormState>();
// final _formKey2 = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Form(
key: _formKey1,
child: Container(
child: Column(
children: [
_buildEmailTF(),
SizedBox(
height: 20,
),
_buildPasswordTF(),
FlatButton(
onPressed: () async {
if (_formKey1.currentState.validate()) {
// dynamic result = await _auth.signUpWithEmailandPassword(
// email, password);
// if (result == null) {
// setState(() => error = "Something is wrong");
// }
print('DOne Working');
}
},
child: Text(
'Done',
))
],
),
),
),
);
}
// bool _rememberMe = false;
Widget _buildEmailTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Email',
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
height: 60.0,
child: TextFormField(
validator: (value) => value.isEmpty ? "Enter an Email" : null,
onChanged: (value) {
setState(() {
email = value;
});
},
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Enter your Email',
),
),
),
],
);
}
Widget _buildPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
height: 60.0,
child: TextFormField(
validator: (value) =>
value.length < 6 ? "More than 6 Character" : null,
onChanged: (value) {
setState(() {
password = value;
});
},
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',
),
),
),
],
);
}
}
I/flutter (24750): DOne Working

How to clear TextFormField's on a form in Flutter?

I have a form that contains 3 TextFormFields. I have a "save" button and a "cancel" button. If the user clicks "cancel" I want to clear the TextFormFields. Can anyone tell me how to do this? Thanks.
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.fromLTRB(30.0, 15.0, 30.0, 15.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15),
Text(
'Display Name',
style: _style,
textAlign: TextAlign.right,
),
SizedBox(height: 5),
TextFormField(
autofocus: true,
initialValue: _displayName,
validator: (value) {
if (value.isEmpty) {
return 'please enter your display name';
}
return null;
},
onSaved: (value) {
_displayName = value;
},
decoration: _textFormFieldDecoration(
hintText: 'your display name',
padding: 12.0,
),
),
...
RaisedButton(
color: kMainColor80,
child: Text('Cancel', style: TextStyle(color: Colors.white, fontSize: 16)),
onPressed: () {
setState(() {
_displayName = '';
_mobileNumber = '';
_emailAddress = '';
});
},
),
You can use the controller.
So, your code should be like:
1st, initialize TextEditingController variable somewhere inside the top of your class:
final myController = TextEditingController();
And then put that controller inside each TextFormField. (Note: I only see your first TextFormField in the code you provided. So, I only put it once. Make sure to put it on each TexFormField)
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.fromLTRB(30.0, 15.0, 30.0, 15.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15),
Text(
'Display Name',
style: _style,
textAlign: TextAlign.right,
),
SizedBox(height: 5),
TextFormField(
controller: myController, // PUT HERE
autofocus: true,
initialValue: _displayName,
validator: (value) {
if (value.isEmpty) {
return 'please enter your display name';
}
return null;
},
onSaved: (value) {
_displayName = value;
},
decoration: _textFormFieldDecoration(
hintText: 'your display name',
padding: 12.0,
),
),
And then, inside the button, call that controller:
RaisedButton(
color: kMainColor80,
child: Text('Cancel', style: TextStyle(color: Colors.white, fontSize: 16)),
onPressed: () {
setState(() {
myController.clear();
});
},
),
If you want each TextFormField to have their own controller, you can create 3 different controllers variable. And thet call each one of them inside you button
you need to add a controller to your TextFormField:
TextFormField(
controller: nameController,
decoration: kTextFieldDecoration.copyWith(
labelText: 'name',
icon: Icon(FontAwesomeIcons.user),
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter Name';
}
return null;
},
),
on your setState()
setState(() {
nameController.text = "";
});
You have to add controller to each text field final TextEditingController _nameController = TextEditingController();
Pass your controller to the text field controller: _nameController,
Now you can clear your text form field using _nameController.clear()
you can do this very easy. just use a TextEditingController like this :
#override
void initState() {
super.initState();
this.display_name_field = new TextEditingController();
}
and when you click on cancel btn you can run this :
this.display_name_field.clear();
I hope I was able to help.

Flutter: keyboard automatically shows up

I'm navigating to the next page within my Flutter app.
On the next page there are a few Forms where a user can enter text.
final _form2Key = GlobalKey<FormState>();
Padding(
padding: EdgeInsets.only(top: 8.0),
child: Container(
width: screenWidth / 1.1,
height: screenHeight / 5.5,
child: Form(
key: _form2Key,
autovalidate: true,
child: TextFormField(
autofocus: true,
validator: (val) {
if (val.trim().length < 3 || val.isEmpty) {
return "Too short";
} else if (val.trim().length > 200) {
return "Too long";
} else {
return null;
}
},
onSaved: (val) => description = val,
decoration: InputDecoration(
border: OutlineInputBorder(),
filled: true,
fillColor: Colors.white,
labelText: "",
labelStyle: TextStyle(fontSize: 15.0),
hintText: " ",
),
),
),
),
Everything 'works', but after navigating to this new page, the keyboard shows up automatically and is focussed on the textfield.
Is it possible to avoid the keyboard popping up and only show the keyboard when the user presses the form?
Thanks in advance!
your keyboard is automatically popping up because you have set autofocus to true, please modify to false or remove that property to avoid keyboard from automatically popping up
final _form2Key = GlobalKey<FormState>();
Padding(
padding: EdgeInsets.only(top: 8.0),
child: Container(
width: screenWidth / 1.1,
height: screenHeight / 5.5,
child: Form(
key: _form2Key,
autovalidate: true,
child: TextFormField(
autofocus: false, // modified
validator: (val) {
if (val.trim().length < 3 || val.isEmpty) {
return "Too short";
} else if (val.trim().length > 200) {
return "Too long";
} else {
return null;
}
},
onSaved: (val) => description = val,
decoration: InputDecoration(
border: OutlineInputBorder(),
filled: true,
fillColor: Colors.white,
labelText: "",
labelStyle: TextStyle(fontSize: 15.0),
hintText: " ",
),
),
),
),
),