Flutter Form widget not validating all fields in the form - flutter

I have a IntlPhoneWidget and a textfield widget inside of a stepper widget. When I press the continue button it only validates the intlphonewidget and not the textfield. Also how do I put in a custom validation message for each of the fields inside of the stepper if those fields are empty?
Here is my code-
#override
Widget build(BuildContext context) {
return Scaffold(
body: Form(
key: _formKey,
child: Stepper(
currentStep: _currentStepper,
onStepContinue: _continueStep,
steps: [
Step(
title: const Text('Enter your name and phone number'),
content: Column(
children: [
TextField(
controller: _displayNameTextFieldController,
),
IntlPhoneField(
decoration: const InputDecoration(
labelText: 'Phone Number',
),
onChanged: (phone) {
setState(() {
_phoneNumber = (phone.completeNumber).trim();
});
},
)
],
),
)
],
),
),
);
}
void _continueStep() {
if (_currentStepper == 0) {
_formKey.currentState?.validate();
}
}

This happened because the IntlPhoneField has built-in validator, but TextField doesn't, if you want to have validator for first field too , you need to use TextFormField instead and set the validator like this:
TextFormField(
controller: _displayNameTextFieldController,
validator: (value) {
if (value != null && value.isEmpty) {
return 'fill name field';
}
return null;
},
)

Related

Keyboard automatically closes in flutter while using form

In my code my keyboard closes automatically when using text formfield and I realized that it closes when I use Form and its key for validation, I am using list view with form but when I remove form it works fine but I need a form to validate, what should I do ?
Form(
key: _formKeyPlant,
child: ListView(children: [
SizedBox(
width: size.width,
child: Column(
children: [
CustomTextField(
controller: name,
title: 'Name',
validator: (text) {
if (text == null || text.isEmpty) {
return 'Required';
} else if (text.contains(RegExp(r'[0-9]')) ||
text.contains(RegExp(r'[#?!#$%^&*-]'))) {
return 'Invalid Input';
}
return null;
},
),
15.verticalSpace,
CustomTextField(
controller: location,
title: 'Location',
validator: (text) {
if (text == null || text.isEmpty) {
return 'Required';
} else if (text.contains(RegExp(r'[0-9]')) ||
text.contains(RegExp(r'[#?!#$%^&*-]'))) {
return 'Invalid Input';
}
return null;
},
),
15.verticalSpace,
CustomTextField(
enabled: false,
onTap: () async {
final response = await showAppBottomSheet(
context,
const TreesInfoBottomSheet(),
);
if (response != null) {
treeType.text = response['name'];
treeTypeId = response['id'];
}
},
controller: treeType,
title: 'Tree Type',
),
15.verticalSpace,
CustomTextField(
controller: ageOfTree,
inputType: TextInputType.number,
validator: (text) {
if (text == null || text.isEmpty) {
return 'Required';
} else if (text.contains(RegExp(r'[a-z]')) ||
text.contains(RegExp(r'[A-Z]')) ||
text.contains(RegExp(r'[#?!#$%^&*-]'))) {
return 'Invalid Input';
}
return null;
},
title: 'Age of Tree',
),
15.verticalSpace,
CustomTextField(
controller: registration,
title: 'Registration ID (Optional)',
),
15.verticalSpace,
CustomTextField(
maxLines: 6,
controller: comments,
labelText: 'comments',
),
},
),
40.verticalSpace,
],
).px(18),
),
]),
),
Correct formate of using textform filed with form and scroll widget is
Please try the below code your keyboard with never hide on textformfiled
final Key _key = GlobalKey();
FocusNode f1 = FocusNode();
FocusNode f2 = FocusNode();
#override
Widget build(BuildContext context) {
return Form(
key: _key,
child: SingleChildScrollView(
child: Column(
children: [
TextFormField(
focusNode: f1,
onFieldSubmitted: (c) {
f1.unfocus();
f2.requestFocus();
},
),
TextFormField(
focusNode: f2,
),
],
),
),
);
}

How to validate the TextFormField as we type in the input in Flutter

I have created a login screen with textformfield for email id and password using flutter. Also, I have added the validation to check these fields. The code is as below;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
theme: ThemeData(
brightness: Brightness.dark,
),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var _formKey = GlobalKey<FormState>();
var isLoading = false;
void _submit() {
final isValid = _formKey.currentState.validate();
if (!isValid) {
return;
}
_formKey.currentState.save();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Form Validation"),
leading: Icon(Icons.filter_vintage),
),
//body
body: Padding(
padding: const EdgeInsets.all(16.0),
//form
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Text(
"Form-Validation In Flutter ",
style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold),
),
//styling
SizedBox(
height: MediaQuery.of(context).size.width * 0.1,
),
TextFormField(
decoration: InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
onFieldSubmitted: (value) {
//Validator
},
validator: (value) {
if (value.isEmpty ||
!RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(value)) {
return 'Enter a valid email!';
}
return null;
},
),
//box styling
SizedBox(
height: MediaQuery.of(context).size.width * 0.1,
),
//text input
TextFormField(
decoration: InputDecoration(labelText: 'Password'),
keyboardType: TextInputType.emailAddress,
onFieldSubmitted: (value) {},
obscureText: true,
validator: (value) {
if (value.isEmpty) {
return 'Enter a valid password!';
}
return null;
},
),
SizedBox(
height: MediaQuery.of(context).size.width * 0.1,
),
RaisedButton(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 15.0,
),
child: Text(
"Submit",
style: TextStyle(
fontSize: 24.0,
),
),
onPressed: () => _submit(),
)
],
),
),
),
);
}
}
The issue I am facing is, I want to validate the fields as soon as the user starts typing the input(dynamically) rather than clicking on the submit button to wait for the validation to happen. I did a lot of research yet could not find a solution. Thanks in advance for any help!
Flutter Form Validation with TextFormField
Here's an alternative implementation of the _TextSubmitWidgetState that uses a Form:
class _TextSubmitWidgetState extends State<TextSubmitForm> {
// declare a GlobalKey
final _formKey = GlobalKey<FormState>();
// declare a variable to keep track of the input text
String _name = '';
void _submit() {
// validate all the form fields
if (_formKey.currentState!.validate()) {
// on success, notify the parent widget
widget.onSubmit(_name);
}
}
#override
Widget build(BuildContext context) {
// build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
decoration: const InputDecoration(
labelText: 'Enter your name',
),
// use the validator to return an error string (or null) based on the input text
validator: (text) {
if (text == null || text.isEmpty) {
return 'Can\'t be empty';
}
if (text.length < 4) {
return 'Too short';
}
return null;
},
// update the state variable when the text changes
onChanged: (text) => setState(() => _name = text),
),
ElevatedButton(
// only enable the button if the text is not empty
onPressed: _name.isNotEmpty ? _submit : null,
child: Text(
'Submit',
style: Theme.of(context).textTheme.headline6,
),
),
],
),
);
}
}
source : https://codewithandrea.com/articles/flutter-text-field-form-validation/
May be this can help someone. Inside the TextFormField use this line of code:
autovalidateMode: AutovalidateMode.onUserInteraction
use autovalidateMode in your Form widget
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: FormUI(),
),

Clear textfield based onchanged (flutter)

TextField(
inputFormatters: [
new FilteringTextInputFormatter.allow(
RegExp('[0-9]')),
],
hintText: 'some text'
title: '',
editingController: controllers[31],
value: somenumber,
onChange: (value) {
if (num.parse(value) <= 3000 &&
num.parse(value) >= 30) {
// save some data
}else{
controllers[31].clear(),
},
),
so above is a textfield with onchange, right now the textfield does not clear if i put outside of the range, is it possible to clear the textfield based onchange?
Is the TextField() you are using part of a plugin? The properties look a bit odd compared with the latest stable release of Flutter.
Here's an example that clears the text:
TextEditingController textEditingController = new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: TextField(
inputFormatters: [
new FilteringTextInputFormatter.allow(RegExp('[0-9]')),
],
decoration: InputDecoration(
hintText: 'some text',
),
controller: textEditingController,
onChanged: (value) {
if (value.length <= 10) {
// something
} else {
textEditingController.clear();
}
}
),
),
);
}
Create TextEditingController for your text field and then assign it to the controller property of TextField.
// create controller
TextEditingController _controller = new TextEditingController();
// assign it to TextField controller property
TextField(
controller : _controller
// your other properties
)
then to clear the text
// clear text
_controller.clear();
``
U can also do this :
TextEditingController textEditingController = new TextEditingController();
Function onchange;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: TextField(
inputFormatters: [
new FilteringTextInputFormatter.allow(RegExp('[0-9]')),
],
decoration: InputDecoration(
hintText: 'some text',
suffixIcon: IconButton(
onPressed: () {
widget.onchanged('');
controller.clear();
},
),
controller: textEditingController,
onChanged: (value) => onchange(value)
}
),
),
);
}

TextFormField cursor did not move when changes occur

I have a screen that shows a textformfield, I want to retrieve the value that the user has inputted. But when I made a change the cursor didn't move, so it stays at position 0. How do I solve this problem?
class ScreenFormArtikel extends StatefulWidget {
final String mode;
ScreenFormArtikel(this.mode);
#override
_ScreenFormArtikelState createState() => _ScreenFormArtikelState();
}
class _ScreenFormArtikelState extends State<ScreenFormArtikel> {
var _key = GlobalKey<FormState>();
var _titleController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Article'),
),
body: Container(
child: Form(
key: _key,
child: Column(
children: [
Consumer<ProviderArtikel>(
builder: (context, artikel, child) {
return TextFormField(
decoration: InputDecoration(
labelText: 'Title',
floatingLabelBehavior: FloatingLabelBehavior.always),
controller: _titleController,
validator: (value) {
if (value.isEmpty) {
return "Please fill this field";
}
return null;
},
onChanged: (value) {
_titleController.text = value;
},
);
},
),
RaisedButton(onPressed: () {}),
],
),
),
),
);
}
}
I have attached the sample video below
click here
Commenting the onChanged will do the work.
TextFormField(
decoration: InputDecoration(
labelText: 'Title',
floatingLabelBehavior: FloatingLabelBehavior.always),
controller: _titleController,
validator: (value) {
if (value.isEmpty) {
return "Please fill this field";
}
return null;
},
// onChanged: (value) {
// _titleController.text = value;
// },
),
Actually the _titleController.text is setting the text onChange, that's why cursor is moving to the first place.
And you don't have to explicitly do the onTextChange thing.

Flutter Web submit form on enter key

Is there a way to call the submit button when a user hits the enter button when filling out a form. Here is my form code:
#override
Widget build(BuildContext context) {
String _email;
return AlertDialog(
title: Text('Password Reset'),
content: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
decoration: InputDecoration(
hintText: 'Email',
labelText: 'Email',
),
autofocus: true,
maxLength: 30,
validator: (value) {
if (value.isEmpty) {
return 'Email is required';
}
return null;
},
onSaved: (input) => _email = input,
),
],
),
),
actions: [
RaisedButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
var result = await auth.sendPasswordResetEmail(_email);
print(result);
Navigator.of(context).pop();
}
},
child: Text('Reset'),
)
],
);
}
For a TextFormField the property to handle this would be onFieldSubmitted. You can copy the code from your onPressed of the RaiseButton to this. For e.g.
onFieldSubmitted: (value) {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
// var result = await auth.sendPasswordResetEmail(_email);
// print(result);
print(_email);
Navigator.of(context).pop();
}
},
A full example is available as a codepen here.
You might be interested in RawKeyboardListener as well however it
doesn't recognize the enter key. But could listen to other keys such as Shift, CapsLock etc.
Use either the onEditingComplete or onSubmitted parameters of the TextFormField constructor, depending on your needs.
Check that the TextFormField has the textInputAction set to TextInputAction.done or TextInputAction.go