I have the following StatefulWidget:
class ProfileScreen extends StatefulWidget {
const ProfileScreen({Key? key}) : super(key: key);
@override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool formIsValid = false;
String fullName = '';
String email = '';
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Form(
key: _formKey,
onChanged: () =>
setState(() => formIsValid = _formKey.currentState!.validate()),
child: Container(
children: [
TextFormField(
textAlign: TextAlign.left,
onChanged: (value) {
setState(() {
fullName = value;
});
},
validator: (String? value) {
return (value == null || value.isEmpty)
? 'Please enter a name'
: null;
},
),
TextFormField(
textAlign: TextAlign.left,
onChanged: (value) {
setState(() {
email = value;
});
},
validator:
validator: (String? value) {
return (value == null || value.isEmpty)
? 'Please enter an email address'
: null;
},
),
SizedBox(
height: 38,
width: 126,
child: ElevatedButton(
onPressed: formIsValid,
style: ElevatedButton.styleFrom(
primary: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(3),
),
),
child: Text(
'UPDATE',
style: const TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
}
}
It works in that the "UPDATE" button is disabled until both fields are valid. However, the TextFormField
errors appear immediately after entering a single character in any field.
How do I only enable the button when all fields are valid without prematurely displaying errors?
NOTE: I don't want to use the reactive_forms package.
CodePudding user response:
you could try checking validation this way
class ProfileScreen extends StatefulWidget {
const ProfileScreen({Key? key}) : super(key: key);
@override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _fullName = TextEditingController();
final _email = TextEditingController();
bool _validate = false;
bool formIsValid = false;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Form(
key: _formKey,
onChanged: () =>
setState(() => formIsValid = _formKey.currentState!.validate()),
child: Column(
children: [
TextFormField(
controller: _fullName,
textAlign: TextAlign.left,
decoration: InputDecoration(
hintText: 'Name',
errorText: _validate ? 'Please enter a name' : null, //here
),
),
TextFormField(
controller: _email,
textAlign: TextAlign.left,
decoration: InputDecoration(
hintText: 'Email',
errorText:
_validate ? 'Please enter an email address' : null, //here
),
),
SizedBox(
height: 38,
width: 126,
child: ElevatedButton(
onPressed: () {
setState(() {
if (_fullName.text.isEmpty || _email.text.isEmpty) {
_validate = true;
print('Not Updated');
} else {
_validate = false;
print('Information Updated');
}
});
},
style: ElevatedButton.styleFrom(
primary: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(3),
),
),
child: const Text(
'UPDATE',
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
}
}
CodePudding user response:
You can create a function
that will check and validate all the TextField
and then return a bool
according to the validation. Put that function in Button
to enable or disable the button as the validation goes.
Function:
bool isOk() {
if (emailId.isNotEmpty) {
if(pass.isNotEmpty){
return true;
} else {
return false;
}
} else {
return false;
}
}
Button:
ElevatedButton(
onPressed: isOk() ? nextClick : null,
child: const Text('Button Text'),
),
CodePudding user response:
You can use a validation function like
bool isValid(){
return fullName!=''&&email != ''
}
Then in your button code use
child: ElevatedButton(
onPressed: isValid()?formIsValid:null,
style: ElevatedButton.styleFrom(
primary: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(3),
),
),
child: Text(
'UPDATE',
style: const TextStyle(
color: Colors.white,
fontSize: 14.0,
fontWeight: FontWeight.bold,
),
),
),
And you can also specify the button style based on the isValid() bool value