I have separated form widgets into separate files And now I am trying to validate form but not working
When I combined all widgets into 1, form validation working
How to do form validation for separate widgets
these are the following code I have done in separate files
class _OnBoardFormState extends State<OnBoardForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
//Selection dropdown for first and Last Name
OnBoardFormName(),
SizedBox(height: 15),
//Selection dropdown for Email
OnBoardFormEmailField(),
SizedBox(height: 15),
//Selection dropdown for Gender
OnBoardFormGenderField(),
SizedBox(height: 15),
//Selection dropdown for Age
OnBoardAgeSelector(),
SizedBox(height: 15),
//Selection dropdown for Hight
OnBoardHeightSelector(),
SizedBox(height: 15),
//Selection dropdown for Kgs and Lbs
OnBoardWeightSelector(),
SizedBox(height: 15),
//Selection dropdown for Location
OnBoardFormLocation(),
SizedBox(height: 40),
//Button to submit the form
//Continue button for next page
OnBoardFormButton(),
],
),
),
);
}
}
And these are the separate widgets
class _OnBoardAgeSelectorState extends State<OnBoardAgeSelector> {
final _formKey = GlobalKey<FormState>();
// age declarations
var _selectedIndexForAge = "Age";
var age = [];
@override
void initState() {
super.initState();
for (int i = 18; i <= 120; i ) {
age.add(i);
}
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'AGE',
style: TextConstants.feildHeadText,
),
const SizedBox(
height: 2,
),
SizedBox(
height: 51,
child: OutlineButton(
shape: const StadiumBorder(),
padding: const EdgeInsets.only(left: 20, right: 10),
highlightedBorderColor: Colors.grey,
borderSide: BorderSide(
color: Colors.grey.shade500,
width: 1,
),
onPressed: () {
// if (_formKey.currentState!.validate()) {
// const Text(
// "Please select Age",
// style: TextStyle(
// color: Colors.red,
// fontSize: 16,
// ),
// );
// }
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return SizedBox(
height: 200,
child: CupertinoPicker(
itemExtent: 32,
onSelectedItemChanged: (int index) {
setState(
() {
_selectedIndexForAge = age[index].toString();
},
);
},
children: List<Widget>.generate(
age.length,
(int index) {
return Center(
child: Text(age[index].toString()),
);
},
),
),
);
},
);
},
child: Stack(
children: [
Align(
alignment: Alignment.centerRight,
child: SvgPicture.asset('assets/icons/dropdown.svg'),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
_selectedIndexForAge.toString(),
textAlign: TextAlign.right,
style: TextConstants.fieldPlaceholderText,
),
),
],
),
),
),
],
);
}
}
and so on and other widgets
when i am trying to validate it shows error like this
CodePudding user response:
You need to add a button inside the form to check the validation.
You need to wrap them in scaffold first
You can use _formKey.currentState!.validate()
To validate all the saperate widgets which are defined in saperate files like "Textformfield" and all...
But all the saperate widgets should come under the form widget and have a for key.
Code (Your updated code)
import 'package:flutter/material.dart';
import 'package:stackexample/onbordname.dart';
class OnBoardForm extends StatefulWidget {
const OnBoardForm({Key? key}) : super(key: key);
@override
_OnBoardFormState createState() => _OnBoardFormState();
}
class _OnBoardFormState extends State<OnBoardForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
//Selection dropdown for first and Last Name
OnBoardFormName(),
SizedBox(height: 15),
//Selection dropdown for Email
OnBoardFormName(),
// OnBoardFormEmailField(),
SizedBox(height: 15),
//Selection dropdown for Gender
OnBoardFormName(),
// OnBoardFormGenderField(),
SizedBox(height: 15),
//Selection dropdown for Age
// OnBoardAgeSelector(),
SizedBox(height: 15),
//Selection dropdown for Hight
// OnBoardHeightSelector(),
SizedBox(height: 15),
//Selection dropdown for Kgs and Lbs
// OnBoardWeightSelector(),
SizedBox(height: 15),
//Selection dropdown for Location
// OnBoardFormLocation(),
SizedBox(height: 40),
Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Good to go...')),
);
}
},
child: const Text('Submit'),
),
),
//Button to submit the form
//Continue button for next page
// OnBoardFormButton(),
],
),
),
),
);
}
}
TextField
import 'package:flutter/material.dart';
class OnBoardFormName extends StatefulWidget {
const OnBoardFormName({Key? key}) : super(key: key);
@override
_OnBoardFormNameState createState() => _OnBoardFormNameState();
}
class _OnBoardFormNameState extends State<OnBoardFormName> {
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'FIRST NAME',
// style: TextConstants.feildHeadText,
),
const SizedBox(
height: 2,
),
TextFormField(
// style: TextConstants.fieldPlaceholderText,
maxLength: 30,
textCapitalization: TextCapitalization.words,
autofocus: false,
decoration: const InputDecoration(
counterText: "",
contentPadding: EdgeInsets.only(left: 20.0, right: 10.0),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xffE3E5F6),
width: 1,
),
borderRadius: BorderRadius.all(Radius.circular(40)),
),
hintText: 'First Name',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter first name';
}
return value.length < 3
? 'Name must be at least 3 to 30 characters long'
: null;
},
),
],
);
}
}
Output
Validation working when charecter less than 3
Validation true
Update
You can't put the button in a new file, Because you can't access the state of that form key
If you strictly want to put the button on other file you need to pass the form key to the new screen ( or file ). or use a state management library like ' Bloc or Provider '
But for now i prefer to put the button on the same file.
Thank you
CodePudding user response:
final form = _formKey.currentState;
if (form.validate()){
form.save();
}
This should be inside Form, form should have _formkey, furthermore you can use autovalidation mode. I think problem is your form.validate() is not inside Form.