I just want to make my TextField as required field, in which I am using Email and password to login for the user. Please let me know how can I make it required and if user don't fill it, how can I give him warning.
TextField (
onChanged: (value) {
email=value;
},
style: const TextStyle(color: Colors.black),
decoration: InputDecoration(
fillColor: Colors.grey.shade100,
filled: true,
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
),
),
const SizedBox(
height: 30,
),
TextField(
onChanged: (value) {
password=value;
},
style: const TextStyle(),
obscureText: true,
decoration: InputDecoration(
fillColor: Colors.grey.shade100,
filled: true,
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
),
),
The esiest way to set a validation logic for the TextField in Flutter is to use TextFormField instead of TextField in combination with Form widget.
It provides you with a callback called validator which is called whenever you call .validate() method in the Form Key.
To learn more about using Form widget in Flutter along with TextFormFiled and validation, check out this video.
Example for a condition in the validator to make the field required:
validator: (String? value) {
if (value == null)
{
return 'This field is required';
}
return null;
},
NOTE:
If the validator callback returned a message, this means the message would be displayed in the errorText for the TextFormField and the .validate() method would return false.
If the validator callback returned null, this means that no errors and the .validate() method would return true.
if user click on submit button then you can check for is email or password field is empty or not empty.
Related
I have this BMI Calculator and I want that the Height can not be under 100 (cm). For that I created a TextFormField which looks like the following:
TextFormField(
onFieldSubmitted: (value) {
setState((){
_heighController.text= value;
if (int.parse(value) >= 100) {
value = "100";
}
value=_heighController.text;
});
},
inputFormatters: [
LengthLimitingTextInputFormatter(3),
FilteringTextInputFormatter.allow(RegExp(r'^[1-9][0-9]*')),
],
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
style: const TextStyle(fontSize: 16, color: Colors.white),
controller: _heighController,
cursorColor: Colors.white,
decoration: InputDecoration(hintText: "in cm", hintStyle: TextStyle(color: Colors.white)),
),
as you can see, I already tried to add onFieldSubmitted, but this doesn't work out like I planned. When I write 90 e.g., it accepts 90 when I press the "enter" button on my keyboard. But when I update the state for this widget with my Plus or minus button (see picture below) it goes to 100 automatically. I want that it goes to 100 every time I leave the "editing option" from this field and the input is below 100. How do I realize that?
You should change the value of the _heighController on your "onFieldSubmitted" function, like this:
onFieldSubmitted: (value) {
setState((){
if (int.parse(value) <= 100) {
value = "100";
}
_heighController.text= value;
});
},
Your error was to attribute the value to your controller before checking the validity.
And after, you set the value of your controller to the parameter of the function, which is pointless in this case.
What is the difference between TextField and TextFormField in flutter? Both look the same. Which one should i use? Which one do you recommend? I use TextField like this:
const TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password',
),
)
A TextFormField mainly has the validator argument, while TextField doesn't: it must return null if the input is valid, and it must return a String if there's some error (usually the String itself contains information about the error). This argument allows you to validate the user input in a very easy way, provided that you include the form fields (there are others, in addition to TextFormField) in a Form widget and that you apply a Key to the Form.
If you do everything correctly, you could just invoke formKey.currentState!.validate() and automatically Flutter will invoke the validator argument for each form field that you added to the Form. If everything checks, the validate will return true, and you can proceed with your program logic. Otherwise, it will return false and it will show the String returned by the validator near the form field that contained incorrect data.
This example is taken from the Flutter cookbook on forms:
[...]
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false otherwise.
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
),
],
),
);
}
}
You use TextFormField when using Form widget. Combined with Form widget you can make more complex forms + validation for whole form.
TextField is basically a TextFormField but you don't have to include it into the Form widget and validation would work a bit differently.
Im using email validator package on flutter to validate the email for login. I have one issue with this package that I want to allow spaces in the email when the user sign in because Im gonna trim the text anyway so I dont want it to show error when there is Spaces at the end.
child: TextFormField(
keyboardType: TextInputType.emailAddress,
controller: emailController,
cursorColor: Colors.white,
textInputAction: TextInputAction.next,
decoration: const InputDecoration(labelText: 'Email'),
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (email) =>
email != null && !EmailValidator.validate(email)
? 'Enter a valid Email' : null,
try {
await _auth.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
Anyone knows how to do it or if there is a better way than using this package?
You don't need to use any package for validating email you can simply do it with RegExp like below in this space is allows and then you can trim it where ever you want to use
validator: (value) {
bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(value!);
if (value == null || value.isEmpty) {
return 'Please Enter Email Address';
}else if (emailValid == false){
return 'Please Enter Valid Email Address';
}
return null;
},
Let me know if you have any questions. Thanks
You can trim email first then you can check for validation.
validator: (email) {
if(email != null) {
email = email.trim();
(!EmailValidator.validate(email))
? 'Enter a valid Email' : null,
}
return null;
}
best practice to use TextFormField validation is to not to allow user to put irrelevant data
TextFormField(
controller: _etcEmail,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
inputFormatter: [
// FilteringTextInputFormatter.allow(RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")),
// FilteringTextInputFormatter.deny(RegExp(r" ")),
FilteringTextInputFormatter.allow(RegExp(r" ")),
],
hintText: 'Email',
validator: (value) {
if (value!.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.pinkAccent,
behavior: SnackBarBehavior.floating,
padding: EdgeInsets.all(5),
content: (Text('Email Field is Required'))));
}
},
read: false,
)
How to can I implement a callback that fires after every few seconds or when user stop typing in TextField ?
Or is it performant to just implement in onChanged callback directly ?
input Field onChanged gives the input value when ever user types in, So you may use onChnaged callback function to save the input, like below,
TextFormField(
controller: _nameController,
onChanged: (value) {
saveData();
},
initialValue: widget.user.userName,
onSaved: (val) {
widget.user.userName = val;
},
validator: (val) =>
val.length > 3 ? null : 'Full name is invalid',
decoration: InputDecoration(
labelText: 'Full Name',
hintText: 'Enter your full name',
icon: Icon(Icons.person),
isDense: true,
),
),
I am added text field in a flutter, but the keypad is overlapping with a text field when we added this in Flutter as view in the existing android app. if the same code runs independently as only Flutter application it will work.
TextFormField(
focusNode: payTMFocus,
controller: payTMController,
inputFormatters: [
LengthLimitingTextInputFormatter(10),
WhitelistingTextInputFormatter.digitsOnly,
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: "Enter mobile number",
filled: true,
hintStyle: getTextStyle(),
hasFloatingPlaceholder: true),
},
validator: (value) {
if (value.length != 10) {
return "Enter valid mobile number";
} else {
return null;
}
},
)
tried seting true to resizeToAvoidBottomPadding for root Scaffold
Github issue link -https://github.com/flutter/flutter/issues/47107
By overlapping means i guess you are not able to see textField as keypad shows over it.
If this is the case then you can use SingleChildScrollView to give scrollable view to area in which your text field is.
child:SingleChildScrollview(
...//container or column or some other widgets you have above in hierarchy
child:TextFormField(
focusNode: payTMFocus,
controller: payTMController,
inputFormatters: [
LengthLimitingTextInputFormatter(10),
WhitelistingTextInputFormatter.digitsOnly,
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: "Enter mobile number",
filled: true,
hintStyle: getTextStyle(),
hasFloatingPlaceholder: true),
},
validator: (value) {
if (value.length != 10) {
return "Enter valid mobile number";
} else {
return null;
}
},
)
),
Hope this helps ! please comment if you are expecting some another solution.
happy to help :)