I've created on the dropdown and i want to validate that dropdown. when a user doesn't select an item from drop-down then it will show a validation.
here is some code I've tried so far.
in this code I've created one drop down when I am click submit then it will show a validation when the user doesn't select an item from the dropdown.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dropdown Validation',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> _type = <String>[
'Passport',
'Driving License',
'Voter ID card',
'Ration Card',
'Aadhar',
'Other Id'
];
String type = 'Local Goverment';
Widget _buildlicenseissuingauthority() {
return FormField(
builder: (FormFieldState state) {
return InputDecorator(
decoration: InputDecoration(
prefixIcon: Icon(Icons.location_on),
labelText: 'Select Personal Identification type',
),
isEmpty: type == '',
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
value: type,
isDense: true,
onChanged: (String newValue) {
setState(() {
type = newValue;
});
},
items: _type.map(
(String value) {
return new DropdownMenuItem(
value: value,
child: new Text(value),
);
},
).toList(),
),
),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[_buildlicenseissuingauthority()],
),
),
);
}
}
please use pacakge https://pub.dev/packages/flutter_form_builder
github https://github.com/danvick/flutter_form_builder
It has more than 10 buildin validators, in your case FormBuilderValidators.required()
code snippet
FormBuilderDropdown(
attribute: "gender",
decoration: InputDecoration(
labelText: "Gender",
icon: const Icon(Icons.category),
hintText: "Select hint",
),
// initialValue: 'Male',
onChanged: _onChanged,
hint: Text('Select Gender'),
validators: [FormBuilderValidators.required()],
items: ['Male', 'Female', 'Other']
.map((gender) => DropdownMenuItem(
value: gender,
child: Text('$gender'),
))
.toList(),
)
full example code
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:intl/intl.dart';
import './data.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter FormBuilder Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
MyHomePageState createState() {
return MyHomePageState();
}
}
class MyHomePageState extends State<MyHomePage> {
var data;
bool autoValidate = true;
bool readOnly = false;
bool showSegmentedControl = true;
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
final GlobalKey<FormFieldState> _specifyTextFieldKey =
GlobalKey<FormFieldState>();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
ValueChanged _onChanged = (val) => print(val);
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("FormBuilder Example"),
),
body: Padding(
padding: EdgeInsets.all(10),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
FormBuilder(
// context,
key: _fbKey,
autovalidate: true,
// readonly: true,
child: Column(
children: <Widget>[
FormBuilderCustomField(
attribute: "name",
validators: [
FormBuilderValidators.required(),
],
formField: FormField(
// key: _fieldKey,
enabled: true,
builder: (FormFieldState<dynamic> field) {
return InputDecorator(
decoration: InputDecoration(
icon: const Icon(Icons.laptop),
hintText: "Select hint",
labelText: "Select option",
contentPadding:
EdgeInsets.only(top: 10.0, bottom: 0.0),
border: InputBorder.none,
errorText: field.errorText,
),
child: DropdownButton(
isExpanded: true,
items: ["One", "Two"].map((option) {
return DropdownMenuItem(
child: Text("$option"),
value: option,
);
}).toList(),
value: field.value,
onChanged: (value) {
field.didChange(value);
},
),
);
},
),
),
FormBuilderChipsInput(
decoration: InputDecoration(
labelText: "Chips",
icon: const Icon(Icons.person),
hintText: "Select hint",
),
attribute: 'chips_test',
// readonly: true,
onChanged: _onChanged,
// valueTransformer: (val) => val.length > 0 ? val[0] : null,
initialValue: [
Contact('Andrew', 'stock#man.com',
'https://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX4057996.jpg'),
],
maxChips: 5,
findSuggestions: (String query) {
if (query.length != 0) {
var lowercaseQuery = query.toLowerCase();
return mockResults.where((profile) {
return profile.name
.toLowerCase()
.contains(query.toLowerCase()) ||
profile.email
.toLowerCase()
.contains(query.toLowerCase());
}).toList(growable: false)
..sort((a, b) => a.name
.toLowerCase()
.indexOf(lowercaseQuery)
.compareTo(b.name
.toLowerCase()
.indexOf(lowercaseQuery)));
} else {
return const <Contact>[];
}
},
chipBuilder: (context, state, profile) {
return InputChip(
key: ObjectKey(profile),
label: Text(profile.name),
avatar: CircleAvatar(
backgroundImage: NetworkImage(profile.imageUrl),
),
onDeleted: () => state.deleteChip(profile),
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
);
},
suggestionBuilder: (context, state, profile) {
return ListTile(
key: ObjectKey(profile),
leading: CircleAvatar(
backgroundImage: NetworkImage(profile.imageUrl),
),
title: Text(profile.name),
subtitle: Text(profile.email),
onTap: () => state.selectSuggestion(profile),
);
},
),
FormBuilderDateTimePicker(
attribute: "date",
onChanged: _onChanged,
inputType: InputType.date,
format: DateFormat("yyyy-MM-dd"),
decoration: InputDecoration(
labelText: "Appointment Time",
icon: const Icon(Icons.calendar_today),
hintText: "Select hint",
),
// readonly: true,
),
FormBuilderSlider(
attribute: "slider",
validators: [FormBuilderValidators.min(6)],
onChanged: _onChanged,
min: 0.0,
max: 10.0,
initialValue: 1.0,
divisions: 20,
decoration: InputDecoration(
labelText: "Number of somethings",
icon: const Icon(Icons.snooze),
hintText: "Select hint",
),
),
FormBuilderCheckbox(
decoration: InputDecoration(
labelText: "terms",
icon: const Icon(Icons.subject),
hintText: "Select hint",
),
attribute: 'accept_terms',
initialValue: false,
onChanged: _onChanged,
leadingInput: true,
label: Text(
"I have read and agree to the terms and conditions"),
validators: [
FormBuilderValidators.requiredTrue(
errorText:
"You must accept terms and conditions to continue",
),
],
),
FormBuilderDropdown(
attribute: "gender",
decoration: InputDecoration(
labelText: "Gender",
icon: const Icon(Icons.category),
hintText: "Select hint",
),
// initialValue: 'Male',
onChanged: _onChanged,
hint: Text('Select Gender'),
validators: [FormBuilderValidators.required()],
items: ['Male', 'Female', 'Other']
.map((gender) => DropdownMenuItem(
value: gender,
child: Text('$gender'),
))
.toList(),
),
FormBuilderTextField(
attribute: "age",
decoration: InputDecoration(
labelText: "Age",
icon: const Icon(Icons.accessibility),
hintText: "Select hint",
),
onChanged: _onChanged,
valueTransformer: (text) => num.tryParse(text),
validators: [
FormBuilderValidators.numeric(),
FormBuilderValidators.max(70),
],
),
FormBuilderTypeAhead(
// initialValue: "Canada",
decoration: InputDecoration(
labelText: "Country",
icon: const Icon(Icons.golf_course),
hintText: "Select hint",
),
attribute: 'country',
onChanged: _onChanged,
itemBuilder: (context, country) {
return ListTile(
title: Text(country),
);
},
suggestionsCallback: (query) {
if (query.length != 0) {
var lowercaseQuery = query.toLowerCase();
return allCountries.where((country) {
return country
.toLowerCase()
.contains(lowercaseQuery);
}).toList(growable: false)
..sort((a, b) => a
.toLowerCase()
.indexOf(lowercaseQuery)
.compareTo(
b.toLowerCase().indexOf(lowercaseQuery)));
} else {
return allCountries;
}
},
),
FormBuilderRadio(
decoration: InputDecoration(
labelText: 'My chosen language',
icon: const Icon(Icons.language),
hintText: "Select hint",
),
attribute: "best_language",
leadingInput: true,
onChanged: _onChanged,
validators: [FormBuilderValidators.required()],
options: [
"Dart",
"Kotlin",
"Java",
"Swift",
"Objective-C"
]
.map((lang) => FormBuilderFieldOption(value: lang))
.toList(growable: false),
),
FormBuilderSegmentedControl(
decoration: InputDecoration(
labelText: "Movie Rating (Archer)",
icon: const Icon(Icons.crop_rotate),
hintText: "Select hint",
),
attribute: "movie_rating",
options: List.generate(5, (i) => i + 1)
.map(
(number) => FormBuilderFieldOption(value: number))
.toList(),
onChanged: _onChanged,
),
FormBuilderSwitch(
decoration: InputDecoration(
labelText: "conditions",
icon: const Icon(Icons.dashboard),
hintText: "Select hint",
),
label: Text('I Accept the tems and conditions'),
attribute: "accept_terms_switch",
initialValue: true,
onChanged: _onChanged,
),
FormBuilderStepper(
decoration: InputDecoration(
labelText: "Stepper",
icon: const Icon(Icons.account_box),
hintText: "Select hint",
),
attribute: "stepper",
initialValue: 10,
step: 1,
validators: [
(val) {
if (!_fbKey.currentState.fields["accept_terms_switch"]
.currentState.value &&
val >= 10) {
return "You can only put more than 10 if you've accepted terms";
}
}
],
),
FormBuilderRate(
decoration: InputDecoration(
labelText: "Rate this form",
icon: const Icon(Icons.branding_watermark),
hintText: "Select hint",
),
attribute: "rate",
iconSize: 32.0,
initialValue: 1,
max: 5,
onChanged: _onChanged,
),
FormBuilderCheckboxList(
decoration: InputDecoration(
labelText: "The language of my people",
icon: const Icon(Icons.collections),
hintText: "Select hint",
),
attribute: "languages",
initialValue: ["Dart"],
leadingInput: true,
options: [
FormBuilderFieldOption(value: "Dart"),
FormBuilderFieldOption(value: "Kotlin"),
FormBuilderFieldOption(value: "Java"),
FormBuilderFieldOption(value: "Swift"),
FormBuilderFieldOption(value: "Objective-C"),
],
onChanged: _onChanged,
),
FormBuilderCustomField(
attribute: 'custom',
valueTransformer: (val) {
if (val == "Other")
return _specifyTextFieldKey.currentState.value;
return val;
},
formField: FormField(
builder: (FormFieldState<String> field) {
var languages = [
"English",
"Spanish",
"Somali",
"Other"
];
return InputDecorator(
decoration: InputDecoration(
labelText: "What's your preferred language?",
icon: const Icon(Icons.bug_report),
hintText: "Select hint",
),
child: Column(
children: languages
.map(
(lang) => Row(
children: <Widget>[
Radio<dynamic>(
value: lang,
groupValue: field.value,
onChanged: (dynamic value) {
field.didChange(lang);
},
),
lang != "Other"
? Text(lang)
: Expanded(
child: Row(
children: <Widget>[
Text(
lang,
),
SizedBox(width: 20),
Expanded(
child: TextFormField(
key:
_specifyTextFieldKey,
),
),
],
),
),
],
),
)
.toList(growable: false),
),
);
},
),
),
FormBuilderSignaturePad(
decoration: InputDecoration(
labelText: "Signature",
icon: const Icon(Icons.card_travel),
hintText: "Select hint",
),
attribute: "signature",
// height: 250,
clearButtonText: "Start Over",
onChanged: _onChanged,
),
],
),
),
Row(
children: <Widget>[
Expanded(
child: MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Submit",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
} else {
print(_fbKey.currentState.value);
print("validation failed");
_scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text('Validation failed'),
duration: Duration(seconds: 3),
));
}
},
),
),
SizedBox(
width: 20,
),
Expanded(
child: MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Reset",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_fbKey.currentState.reset();
},
),
),
],
),
],
),
),
),
);
}
}
Data.dart
class Contact {
final String name;
final String email;
final String imageUrl;
const Contact(this.name, this.email, this.imageUrl);
#override
bool operator ==(Object other) =>
identical(this, other) ||
other is Contact &&
runtimeType == other.runtimeType &&
name == other.name;
#override
int get hashCode => name.hashCode;
#override
String toString() {
return name;
}
}
const allCountries = [
"Afghanistan",
"Albania",
"Algeria",
"American Samoa",
"Andorra",
"Angola",
"Anguilla",
];
const contacts = <Contact>[
Contact('Andrew', 'stock#man.com',
'https://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX4057996.jpg'),
Contact('Paul', 'paul#google.com',
'https://mbtskoudsalg.com/images/person-stock-image-png.png'),
Contact('Fred', 'fred#google.com',
'https://media.istockphoto.com/photos/feeling-great-about-my-corporate-choices-picture-id507296326'),
Contact('Brian', 'brian#flutter.io',
'https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png'),
];
demo, after click submit button, you can see gender has red text "This field can not be empty"
Flutter already has its own Form DropDownButtom for this
List<String> typeNeg = [
"One",
"Two",
"Three",];
String dropdownValue = "One";
DropdownButtonFormField<String>(
value: dropdownValue,
hint: Text("Type of business"),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
validator: (String value) {
if (value?.isEmpty ?? true) {
return 'Please enter a valid type of business';
}
},
items: typeNeg
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onSaved: (val) => setState(() => _user.typeNeg = val),
),
Related
I've a problem with this kind of bug and I hope someone can please tell me how to fix it.
The code:
import 'package:flutter/material.dart';
import 'package:login_form/model/login_model.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final scaffoldKey = GlobalKey<ScaffoldState>();
GlobalKey<FormState> globalFormKey = new GlobalKey<FormState>();
bool hidePassword = true;
LoginRequestModel requestModel;
#override
void initState() {
super.initState();
requestModel = new LoginRequestModel();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
backgroundColor: Theme.of(context).accentColor,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 30, horizontal: 20),
margin: EdgeInsets.symmetric(vertical: 85, horizontal: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Theme.of(context).primaryColor,
boxShadow: [
BoxShadow(
color: Theme.of(context).hintColor.withOpacity(0.2),
offset: Offset(0, 10),
blurRadius: 20)
],
),
child: Form(
key: globalFormKey,
child: Column(
children: <Widget>[
SizedBox(
height: 25,
),
Text(
"Login",
style: Theme.of(context).textTheme.headline2,
),
SizedBox(
height: 20,
),
new TextFormField(
keyboardType: TextInputType.emailAddress,
onSaved: (input) => requestModel.email = input,
validator: (input) =>
!(input?.contains("#") ?? false)
? "Email id Should be valid"
: null,
decoration: new InputDecoration(
hintText: "Email Address",
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context)
.accentColor
.withOpacity(0.2),
)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).accentColor)),
prefixIcon: Icon(Icons.email,
color: Theme.of(context).accentColor),
),
),
SizedBox(
height: 20,
),
new TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => requestModel.password = input,
validator: (input) => (input != null &&
input.length < 3)
? "Password should be more than < 3 characters"
: null,
obscureText: hidePassword,
decoration: new InputDecoration(
hintText: "Password",
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context)
.accentColor
.withOpacity(0.2),
)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).accentColor)),
prefixIcon: Icon(Icons.lock,
color: Theme.of(context).accentColor),
suffixIcon: IconButton(
onPressed: () {
setState(() {
hidePassword = !hidePassword;
});
},
icon: Icon(hidePassword
? Icons.visibility_off
: Icons.visibility),
),
),
),
SizedBox(
height: 30,
),
TextButton(
child: Text(
"Login",
style: TextStyle(color: Colors.white),
),
onPressed: () {
if (validateAndSave()) {
print(requestModel.toJson());
}
},
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(
vertical: 12,
horizontal: 80,
),
backgroundColor:
Theme.of(context).accentColor,
shape: StadiumBorder())),
],
),
),
),
],
)
],
),
));
}
bool validateAndSave() {
final form = globalFormKey.currentState;
if (form!.validate()) {
form.save();
return true;
}
return false;
}
}
this is my Loginmodel.dart code
class LoginResponseModel {
final String status;
final String message;
final String kid;
final String uid;
final String email;
final String password;
LoginResponseModel({
required this.status,
required this.message,
required this.kid,
required this.uid,
required this.email,
required this.password});
factory LoginResponseModel.fromJson(Map<String, dynamic> json) {
return LoginResponseModel(
status: json["status"] as String? ?? "",
message: json["message"] as String? ?? "",
kid: json["kid"] as String? ?? "",
uid: json["uid"] as String? ?? "",
email: json["email"] as String? ?? "",
password: json["password"] as String? ?? "",
);
}
}
class LoginRequestModel {
String email;
String password;
LoginRequestModel({
required this.email,
required this.password,
});
Map<String, dynamic> toJson() {
Map<String, dynamic> map = {
'email': email.trim(),
'password': password.trim(),
};
return map;
}
}
The error:
The Error On LoginRequestModel requestModel; says " Non Nullable Instance field 'requestModel' must be initialized.
Then Error message on requestModel = new LoginRequestModel() says The Named Parameter 'email is required, but there's no corresponding argument.
And Last On OnSaved = input says "A value of type 'String?' can't be assigned to a variable of type 'string'."
I really appreciate the answer you gave
The Error On LoginRequestModel requestModel; says " Non Nullable Instance field 'requestModel' must be initialized.
You need to change:
LoginRequestModel requestModel;
Into the following since you are first setting the value in initState and therefore the variable are not going to be given a value right away then the object is created:
late LoginRequestModel requestModel;
Then Error message on requestModel = new LoginRequestModel() says The
Named Parameter 'email is required, but there's no corresponding
argument.
I don't know the content of the class LoginRequestModel but I would guess it has a named parameter email which is required to be specified when calling the LoginRequestModel constructor.
And Last On OnSaved = input says "A value of type 'String?' can't be assigned to a variable of type 'string'."
Again, I don't know your LoginRequestModel class but I would guess the email field is not nullable. That is a problem since onSave expects a method with the signature:
void FormFieldSetter<T>(
T? newValue
)
So your code here does not take into account that input is a nullable variable:
onSaved: (input) => requestModel.email = input
Since some of your problems is related to issues with Dart null-safety I will recommend you to read: https://dart.dev/null-safety
One by One,
The first one, you defined LoginRequestModel requestModel as non-nullable by default means that this variable is declared normally cannot be null. more detail You could just change LoginRequestModel requestModel; to LoginRequestModel requestModel= new LoginRequestModel();, instead of giving a value in initState. It looks like
LoginRequestModel requestModel = new LoginRequestModel();
#override
void initState() {
super.initState();
// requestModel = new LoginRequestModel();
}
Or use late (It is expensive)
Second one, I think in LoginRequestModel will lool like this LoginRequestModel({#required this.email}). You can choose to remove #required or give a empty value.
Last one, since requestModel.password and requestModel.email is non-nullable, it should like onSaved: (input) => requestModel.email = input!;
I think this should fix your problem.
In order to solve the error
assign the value of requestModel at the time of declaring it instead of in initState.
pass empty string as arguments to LoginRequestModel because email and password are required field.
write input! instead of input to indicate that input is not null
import 'package:flutter/material.dart';
import 'package:login_form/model/login_model.dart';
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final scaffoldKey = GlobalKey<ScaffoldState>();
GlobalKey<FormState> globalFormKey = new GlobalKey<FormState>();
bool hidePassword = true;
LoginRequestModel requestModel = new LoginRequestModel('','');
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
backgroundColor: Theme.of(context).accentColor,
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 30, horizontal: 20),
margin: EdgeInsets.symmetric(vertical: 85, horizontal: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Theme.of(context).primaryColor,
boxShadow: [
BoxShadow(
color: Theme.of(context).hintColor.withOpacity(0.2),
offset: Offset(0, 10),
blurRadius: 20)
],
),
child: Form(
key: globalFormKey,
child: Column(
children: <Widget>[
SizedBox(
height: 25,
),
Text(
"Login",
style: Theme.of(context).textTheme.headline2,
),
SizedBox(
height: 20,
),
new TextFormField(
keyboardType: TextInputType.emailAddress,
onSaved: (input) => requestModel.email = input!,
validator: (input) =>
!(input?.contains("#") ?? false)
? "Email id Should be valid"
: null,
decoration: new InputDecoration(
hintText: "Email Address",
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context)
.accentColor
.withOpacity(0.2),
)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).accentColor)),
prefixIcon: Icon(Icons.email,
color: Theme.of(context).accentColor),
),
),
SizedBox(
height: 20,
),
new TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => requestModel.password = input!,
validator: (input) => (input != null &&
input.length < 3)
? "Password should be more than < 3 characters"
: null,
obscureText: hidePassword,
decoration: new InputDecoration(
hintText: "Password",
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context)
.accentColor
.withOpacity(0.2),
)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).accentColor)),
prefixIcon: Icon(Icons.lock,
color: Theme.of(context).accentColor),
suffixIcon: IconButton(
onPressed: () {
setState(() {
hidePassword = !hidePassword;
});
},
icon: Icon(hidePassword
? Icons.visibility_off
: Icons.visibility),
),
),
),
SizedBox(
height: 30,
),
TextButton(
child: Text(
"Login",
style: TextStyle(color: Colors.white),
),
onPressed: () {
if (validateAndSave()) {
print(requestModel.toJson());
}
},
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(
vertical: 12,
horizontal: 80,
),
backgroundColor:
Theme.of(context).accentColor,
shape: StadiumBorder())),
],
),
),
),
],
)
],
),
));
}
bool validateAndSave() {
final form = globalFormKey.currentState;
if (form!.validate()) {
form.save();
return true;
}
return false;
}
}
I am new to flutter and i am building a Notes App. In my project i create three files main.dart, addUser.dart & editUser.dart My CREATE operation(addUser.dart) works properly & READ operation(main.dart) as well but when i click on read operation note it shows an red error with warning Bad state: field does not exist within the DocumentSnapshotPlatform
I am getting this error:
════════ Exception caught by widgets library ═══════════════════════════════════
The following StateError was thrown building Builder(dirty):
Bad state: field does not exist within the DocumentSnapshotPlatform
The relevant error-causing widget was
MaterialApp
lib\main.dart:18
When the exception was thrown, this was the stack
#0 DocumentSnapshotPlatform.get._findKeyValueInMap
package:cloud_firestore_platform_interface/…/platform_interface/
platform_interface_document_snapshot.dart:82
#1 DocumentSnapshotPlatform.get._findComponent
package:cloud_firestore_platform_interface/…/platform_interface/
platform_interface_document_snapshot.dart:98
#2 DocumentSnapshotPlatform.get
package:cloud_firestore_platform_interface/…/platform_interface/
platform_interface_document_snapshot.dart:113
#3 DocumentSnapshot.get
package:cloud_firestore/src/document_snapshot.dart:49
#4 DocumentSnapshot.[]
package:cloud_firestore/src/document_snapshot.dart:56
...
════════════════════════════════════════════════════════════════════════════════
Reloaded 2 of 826 libraries in 14,160ms.
Restarted application in 11,595ms.
W/DynamiteModule(10940): Local module descriptor class for providerinstaller not found.
I/DynamiteModule(10940): Considering local module providerinstaller:0 and remote module
providerinstaller:0
W/ProviderInstaller(10940): Failed to load providerinstaller module: No acceptable module found.
Local version is 0 and remote version is 0.
════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 240 pixels on the bottom.
The relevant error-causing widget was
Column
lib\main.dart:96
To inspect this widget in Flutter DevTools, visit: http://127.0.0.1:9101/#/inspector?
uri=http%3A%2F%2F127.0.0.1%3A52941%2F0C0SU5iODJs%3D%2F&inspectorRef=inspector-0
The overflowing RenderFlex has an orientation of Axis.vertical.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be seen.
If the content is legitimately bigger than the available space, consider clipping it with a ClipRect
widget before putting it in the flex, or using a scrollable container rather than a Flex, like a
ListView.
The specific RenderFlex in question is: RenderFlex#b9fbf relayoutBoundary=up10 OVERFLOWING
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by rendering library ═════════════════════════════════
A RenderFlex overflowed by 240 pixels on the bottom.
The relevant error-causing widget was
Column
lib\main.dart:96
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════
Bad state: field does not exist within the DocumentSnapshotPlatform
The relevant error-causing widget was
MaterialApp
lib\main.dart:18
════════════════════════════════════════════════════════════════════════════════
my Main.dart file
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:darwish_latest/addNote.dart';
import 'package:darwish_latest/editNote.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
CollectionReference ref = FirebaseFirestore.instance.collection('darwish');
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("UMHE Note"),
),
floatingActionButton: FloatingActionButton(
// backgroundColor: Colors.black,
child: Icon(Icons.add),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (_) => AddNote()));
}),
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("darwish")
.orderBy("time")
.snapshots(),
builder: (context, snapshot) {
return ListView.builder(
itemCount:
snapshot.hasData ? snapshot.data.documents.length : 0,
itemBuilder: (_, index) {
var darwish = snapshot.data.documents[index];
return snapshot.data.documents.length == 0
? Text("Text Notes Found")
: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => EditNote(
darwish['empId'], darwish.id)));
},
child: Container(
margin: EdgeInsets.all(10),
constraints: BoxConstraints(maxHeight: 150),
color: Colors.grey.withOpacity(0.4),
child: Column(children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(darwish['empid'],
style: GoogleFonts.sourceCodePro(
fontSize: 20)),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(darwish['user'],
style: GoogleFonts.sourceCodePro(
fontSize: 20)),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(darwish['email'],
style: GoogleFonts.sourceCodePro(
fontSize: 20)),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(darwish['password'],
style: GoogleFonts.sourceCodePro(
fontSize: 20)),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(darwish['DOB'],
style: GoogleFonts.sourceCodePro(
fontSize: 20)),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(darwish['address'],
style: GoogleFonts.sourceCodePro(
fontSize: 20)),
),
]),
),
);
});
},
));
}
}
my addNote.dart file
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class AddNote extends StatefulWidget {
#override
_AddNoteState createState() => _AddNoteState();
}
class _AddNoteState extends State<AddNote> {
GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController empId = TextEditingController();
TextEditingController user = TextEditingController();
TextEditingController emailid = TextEditingController();
TextEditingController passwordd = TextEditingController();
TextEditingController dobirth = TextEditingController();
TextEditingController myaddress = TextEditingController();
CollectionReference ref = FirebaseFirestore.instance.collection('darwish');
String empid = '';
String username = '';
String email = '';
String password = '';
String dob = '';
String address = '';
buildEmployeeid() => TextFormField(
controller: empId,
decoration: InputDecoration(
labelText: 'Employee Id',
border: OutlineInputBorder(),
),
validator: (value) {
if (value.isEmpty) {
return 'Employee id can not be empty';
}
return null;
},
onSaved: (value) => setState(() => empid = value),
);
Widget buildUsername() => TextFormField(
controller: user,
decoration: InputDecoration(
labelText: 'Username',
border: OutlineInputBorder(),
),
validator: (value) {
if (value.isEmpty) {
return 'Title can not be empty';
}
return null;
},
maxLength: 30,
onSaved: (value) => setState(() => username = value),
);
Widget buildEmail() => TextFormField(
controller: emailid,
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
validator: (value) {
final pattern =
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+";
final regExp = RegExp(pattern);
if (value.isEmpty) {
return 'Email can not be empty';
} else if (!regExp.hasMatch(value)) {
return 'Enter a valid email';
}
return null;
},
keyboardType: TextInputType.emailAddress,
onSaved: (value) => setState(() => email = value),
);
Widget buildPassword() => TextFormField(
controller: passwordd,
decoration: InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(),
),
validator: (value) {
if (value.isEmpty) {
return 'Password can not be empty';
}
return null;
},
onSaved: (value) => setState(() => password = value),
obscureText: true,
);
buildDOB() => TextFormField(
controller: dobirth,
decoration: InputDecoration(
labelText: 'Date Of Birth',
border: OutlineInputBorder(),
),
validator: (value) {
if (value.isEmpty) {
return 'Date of Birth can not be empty';
}
return null;
},
onSaved: (value) => setState(() => dob = value),
);
buildAddress() => TextFormField(
controller: myaddress,
decoration: InputDecoration(
labelText: 'Address',
border: OutlineInputBorder(),
),
validator: (value) {
if (value.isEmpty) {
return 'Address can not be empty';
}
return null;
},
maxLength: 30,
onSaved: (value) => setState(() => address = value),
);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
'UMHE Form',
),
),
body: Form(
key: formKey,
// autovalidate: true,
child: ListView(
padding: EdgeInsets.all(16),
children: [
buildEmployeeid(),
const SizedBox(height: 32),
buildUsername(),
const SizedBox(height: 16),
buildEmail(),
const SizedBox(height: 32),
buildPassword(),
const SizedBox(height: 32),
buildDOB(),
const SizedBox(height: 32),
buildAddress(),
const SizedBox(height: 32),
ElevatedButton(
child: Text(
'Submit',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
onPressed: () {
final isValid = formKey.currentState.validate();
FocusScope.of(context).unfocus();
if (isValid) {
// formKey.currentState.save();
ref.add({
'empid': empId.text,
'user': user.text,
'email': emailid.text,
'password': passwordd.text,
'DOB': dobirth.text,
'address': myaddress.text,
'time': DateTime.now()
});
formKey.currentState.reset();
return AlertDialog(
content: Text('Saved Successfully...'),
);
}
}),
],
),
),
);
}
}
my myEdit.dart file
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class EditNote extends StatefulWidget {
String id;
String docid;
EditNote(id, docid);
#override
_EditNoteState createState() => _EditNoteState();
}
class _EditNoteState extends State<EditNote> {
GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController empId = TextEditingController();
TextEditingController user = TextEditingController();
TextEditingController emailid = TextEditingController();
TextEditingController passwordd = TextEditingController();
TextEditingController dobirth = TextEditingController();
TextEditingController myaddress = TextEditingController();
#override
void initState() {
empId.text = widget.id;
}
CollectionReference ref = FirebaseFirestore.instance.collection("darwish");
editEmployeeId() => TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Employee Id can not be empty';
}
return null;
},
controller: empId,
decoration: InputDecoration(
// fillColor: Colors.grey.withOpacity(0.4),
filled: true,
hintText: 'Employee Id',
),
style: GoogleFonts.sourceCodePro(
fontSize: 25,
// color: Colors.black,
fontWeight: FontWeight.bold),
);
editUser() => TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'User can not be empty';
}
return null;
},
controller: user,
decoration: InputDecoration(
// fillColor: Colors.grey.withOpacity(0.4),
filled: true,
hintText: 'User',
),
style: GoogleFonts.sourceCodePro(
fontSize: 25,
// color: Colors.black,
fontWeight: FontWeight.bold),
);
editEmailId() => TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email Id can not be empty';
}
return null;
},
controller: emailid,
decoration: InputDecoration(
// fillColor: Colors.grey.withOpacity(0.4),
filled: true,
hintText: 'Email Id',
),
style: GoogleFonts.sourceCodePro(
fontSize: 25,
// color: Colors.black,
fontWeight: FontWeight.bold),
);
editPassword() => TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Password can not be empty';
}
return null;
},
controller: passwordd,
decoration: InputDecoration(
// fillColor: Colors.grey.withOpacity(0.4),
filled: true,
hintText: 'Password',
),
style: GoogleFonts.sourceCodePro(
fontSize: 25,
// color: Colors.black,
fontWeight: FontWeight.bold),
);
editDOB() => TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'DOB can not be empty';
}
return null;
},
controller: dobirth,
decoration: InputDecoration(
// fillColor: Colors.grey.withOpacity(0.4),
filled: true,
hintText: 'Date Of Birth',
),
style: GoogleFonts.sourceCodePro(
fontSize: 25,
// color: Colors.black,
fontWeight: FontWeight.bold),
);
editMyAddress() => TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Address can not be empty';
}
return null;
},
controller: myaddress,
decoration: InputDecoration(
// fillColor: Colors.grey.withOpacity(0.4),
filled: true,
hintText: 'Employee Id',
),
style: GoogleFonts.sourceCodePro(
fontSize: 25,
// color: Colors.black,
fontWeight: FontWeight.bold),
);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Edit Note"),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: () => {Navigator.pop(context)}),
actions: [
IconButton(
icon: Icon(
Icons.delete,
color: Colors.white,
),
onPressed: () {
FirebaseFirestore.instance
.collection('darwish')
.doc(widget.docid)
.delete()
.then((value) => Navigator.pop(context));
}),
],
),
body: Form(
key: formKey,
child: ListView(
padding: EdgeInsets.all(16),
children: [
editEmployeeId(),
const SizedBox(height: 16),
editUser(),
const SizedBox(height: 32),
editEmailId(),
const SizedBox(height: 32),
editPassword(),
const SizedBox(height: 32),
editDOB(),
const SizedBox(height: 32),
editMyAddress(),
ElevatedButton(
child: Text(
'Update',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
onPressed: () {
if (formKey.currentState.validate()) {
FirebaseFirestore.instance
.collection("darwish")
.doc(widget.docid)
.set({
'empid': empId.text,
'user': user.text,
'email': emailid.text,
'password': passwordd.text,
'DOB': dobirth.text,
'address': myaddress.text,
// 'content': content.text,
'time': DateTime.now()
}).then((value) => Navigator.pop(context));
}
}),
],
)));
}
}
Validation is working well but incase of validation error, option to select on option is disabled.
DropdownButtonFormField(
isExpanded: true,
hint: Text('Gender'),
value: _selectedGender,
onChanged: (newValue) {
setState(() {
_selectedGender = newValue;
});
},
items: _gender.map((gender) {
return DropdownMenuItem(
child: new Text(gender),
value: gender,
);
}).toList(),
validator: (value) {
if (value == null)
return "Please select your gender";
return null;
},
),
Above code is in a page view,
my variables
List<String> _gender = ['Male', 'Female'];
String _selectedGender;
My entire Form code : just reduced to one field its very long
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
final List<GlobalKey<FormState>> _page = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
];
final _key = GlobalKey<ScaffoldState>();
List<String> _gender = ['Male', 'Female'];
String _selectedGender;
void changePage() {
if (currentPageValue < 3) {
if (_page[currentPageValue].currentState.validate()) {
setState(() {
currentPageValue += 1;
});
}
}
}
#override
Widget build(BuildContext context) {
var deviceSize = MediaQuery.of(context).size;
var deviceWidth = deviceSize.width;
return Scaffold(
key: _key,
backgroundColor: _backgroundColor,
appBar: AppBar(
backgroundColor: _backgroundColor,
leading: IconButton(
icon: Icon(
currentPageValue == 0 ? Icons.close : Icons.keyboard_backspace,
size: 20.0,
color: _headerColor,
),
onPressed: currentPageValue == 0
? () => Navigator.pop(context)
: () => back()),
centerTitle: true,
elevation: 0.0,
),
body: Form(
key: _page[0],
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: deviceWidth * 0.9,
height: dropDownHeight,
child: ButtonTheme(
child: DropdownButtonFormField(
isExpanded: true,
hint: Text('Gender'),
value: _selectedGender,
onChanged: (newValue) {
setState(() {
_selectedGender = newValue;
});
},
items: _gender.map((gender) {
return DropdownMenuItem(
child: new Text(gender),
value: gender,
);
}).toList(),
validator: (value) {
if (value == null) return "Please select your gender";
return null;
},
),
),
),
RaisedButton(
color: buttonColor,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10.0),
),
child: Text(
'Next',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w400,
),
),
onPressed: () => changePage(),
),
],
),
),
),
);
Looking at your code, I strongly recommend you create 3 different Forms and validate them separately, so you don't have any problem regarding form state. To achieve this, you can just wrap the fields into their respective Form and be sure not to mix the forms nor have them one inside the other.
Below, an example based on your code and on what I have said:
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
final _page1 = GlobalKey<FormState>();
final _page2 = GlobalKey<FormState>();
final _page3 = GlobalKey<FormState>();
final _key = GlobalKey<ScaffoldState>();
int currentPageValue;
List<String> _gender = ['Male', 'Female'];
String _selectedGender;
void changePage(GlobalKey<FormState> page) {
if (currentPageValue < 3) {
if (page.currentState.validate()) {
setState(() {
currentPageValue += 1;
});
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _key,
body: ListView(
children: <Widget>[
Form(
key: _page1,
child: Column(
children: [
DropdownButtonFormField(
isExpanded: true,
hint: Text('Gender'),
value: _selectedGender,
onChanged: (newValue) {
setState(() {
_selectedGender = newValue;
});
},
items: _gender.map((gender) {
return DropdownMenuItem(
child: new Text(gender),
value: gender,
);
}).toList(),
validator: (value) {
if (value == null) return "Please select your gender";
return null;
},
),
RaisedButton(
child: Text('Next'),
onPressed: () => changePage(_page1),
),
],
),
),
Form(
key: _page2,
child: Column(
children: [
// SomeField(
//
// ),
// SomeOtherField(
//
// ),
RaisedButton(
child: Text('Next'),
onPressed: () => changePage(_page2),
),
],
),
),
],
),
);
}
}
i want to create a registration form but I get an error as below. Type form elements work, but when buildMail is active, the widget validation that I created with buildName does not work.
Edit: It verifies up to 7 Textformfield in total, but when there are more than 7 Textformfield, it doesn't check for more, is there a Textformfield number limit for verification?
ScreenShot
My Code
class RegisterForm extends StatefulWidget {
#override
_RegisterFormState createState() => _RegisterFormState();
}
class _RegisterFormState extends State<RegisterForm> {
final _formkey = GlobalKey<FormState>();
TextEditingController nameController = TextEditingController();
TextEditingController surNameController = TextEditingController();
TextEditingController userNameController = TextEditingController();
TextEditingController passWordController = TextEditingController();
TextEditingController passWordController2 = TextEditingController();
TextEditingController phoneController = TextEditingController();
TextEditingController phoneController2 = TextEditingController();
TextEditingController phoneController3 = TextEditingController();
TextEditingController cityCodeController = TextEditingController();
TextEditingController epostaController = TextEditingController();
int genderInt;
bool hatirlaDeger = false;
Widget buildName() {
return TextFormField(
controller: nameController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Ad",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
keyboardType: TextInputType.text,
validator: (value) {
if (value.isEmpty) {
return "Bu alan boş bırakılamaz";
} else if (value.length < 2) {
return "Ad alanı en az 2 karakterli olmalıdır";
} else if (value.length > 15) {
return "Ad alanı en fazla 15 karakterli olabilir";
}
},
);
}
Widget buildSurame() {
return TextFormField(
controller: surNameController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Soyad",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
keyboardType: TextInputType.text,
validator: (value) {
if (value.isEmpty) {
return "Bu alan boş bırakılamaz";
} else if (value.length < 2) {
return "Soyad alanı en az 2 karakterli olmalıdır";
} else if (value.length > 15) {
return "Soyad alanı en fazla 15 karakterli olabilir";
}
},
);
}
// Widget buildMail() {
// return TextFormField(
// controller: epostaController,
// decoration: InputDecoration(
// prefixIcon: Icon(Icons.mail),
// labelText: "E-Mail",
// helperText: "",
// fillColor: Colors.red,
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(10),
// borderSide: BorderSide(),
// ),
// ),
// keyboardType: TextInputType.text,
// validator: (value) {
// if (value.length == 2) {
// return "test";
// }
// },
// );
// }
Widget buildUsername() {
return TextFormField(
controller: userNameController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Kullanıcı Adı",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
keyboardType: TextInputType.text,
validator: (value) {
if (value.isEmpty) {
return "Bu alan boş bırakılamaz";
} else if (value.length < 4) {
return "Kullanıc adı alanı en az 4 karakterli olmalıdır";
} else if (value.length > 15) {
return "Kullanıc adı alanı en fazla 15 karakterli olabilir";
}
},
);
}
Widget buildPassWord() {
return TextFormField(
controller: passWordController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Parola",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
obscureText: true,
keyboardType: TextInputType.visiblePassword,
validator: (value) {
if (value.isEmpty) {
return "Bu alan boş bırakılamaz";
} else if (value.length < 6) {
return "Parola alanı en az 6 karakterli olmalıdır";
}
},
);
}
Widget buildConfirmPassWord() {
return TextFormField(
controller: passWordController2,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Parola Doğrulama",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
obscureText: true,
keyboardType: TextInputType.visiblePassword,
validator: (value) {
if (passWordController2.text != passWordController.text) {
return "Parolalar eşleşmiyor";
}
},
);
}
Widget buildPhone() {
return TextFormField(
controller: phoneController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Telefon",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
keyboardType: TextInputType.number,
validator: (value) {
if (value.length != 10) {
return "Telefon alanı 10 karakterli olmalıdır";
}
if (value[0] == "0") {
return "0 ile başlayamaz";
}
},
);
}
Widget buildPhone2() {
return TextFormField(
controller: phoneController2,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Telefon2",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
keyboardType: TextInputType.number,
validator: (value) {
if (value.length != 30) {
return "Telefon alanı 10 karakterli olmalıdır";
}
},
);
}
Widget buildPhone3() {
return TextFormField(
controller: phoneController3,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Telefon3",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
keyboardType: TextInputType.number,
validator: (value) {
if (value.length != 30) {
return "Telefon alanı 10 karakterli olmalıdır";
}
},
);
}
Widget buildCityCode() {
return TextFormField(
controller: cityCodeController,
decoration: InputDecoration(
prefixIcon: Icon(Icons.short_text),
labelText: "Plaka",
helperText: "",
fillColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(),
),
),
keyboardType: TextInputType.number,
validator: (value) {
if (value.length != 2) {
return "Plaka alanı 2 karakterli olmalıdır";
}
if (int.parse(value) < 1 || int.parse(value) > 81) {
return "Plaka kodu geçerli değil";
}
},
);
}
Widget genderPick() {
return GenderPickerWithImage(
maleText: "Erkek",
femaleText: "Kadın",
isCircular: true,
showOtherGender: false,
verticalAlignedText: false,
equallyAligned: false,
animationDuration: Duration(milliseconds: 300),
opacityOfGradient: 0.4,
padding: const EdgeInsets.all(5),
size: MediaQuery.of(context).size.aspectRatio * 120,
selectedGender: Gender.Female,
selectedGenderTextStyle:
TextStyle(color: Color(0xFF8b32a8), fontWeight: FontWeight.bold),
unSelectedGenderTextStyle:
TextStyle(color: Colors.white, fontWeight: FontWeight.normal),
onChanged: (Gender gender) {
if (gender == Gender.Female) {
genderInt = 0;
} else {
genderInt = 1;
}
},
);
}
Widget datePick() {
return Container(
height: 100,
child: CupertinoDatePicker(
minimumYear: 1900,
maximumYear: DateTime.now().year - 12,
mode: CupertinoDatePickerMode.date,
initialDateTime: DateTime(DateTime.now().year - 12),
onDateTimeChanged: (DateTime newDateTime) {},
),
);
}
Widget accept() {
return Row(
children: [
Checkbox(
activeColor: Colors.orange,
value: hatirlaDeger,
checkColor: Colors.white,
onChanged: (checkDeger) {
setState(() {
hatirlaDeger = checkDeger;
});
},
),
GestureDetector(
child: Text(
"Kullanım Koşullarını Kabul Ediyorum",
style:
TextStyle(fontSize: MediaQuery.of(context).size.width * 0.031),
),
),
],
);
}
Widget regButton() {
return Row(
children: <Widget>[
Expanded(
child: RaisedButton(
child: Text(
"Kayıt Ol",
style: TextStyle(color: Colors.white),
),
color: Colors.amber,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(color: Colors.transparent)),
onPressed: () {
if (_formkey.currentState.validate()) {
print("Doğru");
} else {
print("Yanlış");
}
},
),
),
],
);
}
Widget cancelButton() {
return Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Colors.blue,
child: Text(
"Vazgeç",
style: TextStyle(color: Colors.white),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(color: Colors.transparent)),
onPressed: () {
Navigator.popAndPushNamed(context, "/");
},
),
),
],
);
}
#override
Widget build(BuildContext context) {
return Form(
// autovalidate: true,
key: _formkey,
child: ListView(
children: [
buildName(),
buildSurame(),
buildUsername(),
buildPassWord(),
buildConfirmPassWord(),
buildPhone(),
buildPhone2(),
buildPhone3(),
buildCityCode(),
genderPick(),
Divider(),
datePick(),
accept(),
regButton(),
cancelButton(),
],
),
);
}
}
Here, I am trying flutter_form_builder for the dropdown. but there is some problem when I check the validation of all fields while button clicks on the Next button. it will check the form state is valid or not. if I click on the next button it will show all the required filed it will show me dropdown also but id I am not the select value from drop-down then it needs do not redirect any other page without selecting dropdown value because there is required validation. so the issue is drop-down validation is showing but not working.
Here is code of my screen :
class _AddWalkinServiceScheduleScreenState
extends State<AddWalkinServiceScheduleScreen>
with TickerProviderStateMixin {
final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
AddWalkinModel model;
bool autovalidate = false;
final TextEditingController _bspBusinessLegalAddress =
TextEditingController();
LocationResult _pickedLocation;
Map<String, dynamic> _typeValue;
AnimationController controller;
Animation<double> animation;
final TextEditingController _serviceDate = TextEditingController();
TextEditingController _serviceTime = new TextEditingController();
String _isoDate;
String addresschoice;
List<String> _imageFilesList2 = [];
List<File> _licenseImages2 = [];
bool _isFlexible = false;
String _serviceType;
List<dynamic> _type = <dynamic>[];
#override
void initState() {
super.initState();
}
Widget _builddate() {
return Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5.0),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 11),
child: Text(
"Date",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
_buildservicedate(),
],
),
);
}
Widget _buildselectAddress() {
return Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5.0),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 11),
child: Text(
"Select Address",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
_buildaddresschoice(),
addresschoice == "Current Location"
? _addressTextfield()
: (addresschoice == "Select from address book" ||
model.address != null)
? _addressTextfield()
: SizedBox(),
_buildServicetype()
],
),
);
}
Widget _addressTextfield() {
return TudoTextWidget(
prefixIcon: Icon(FontAwesomeIcons.mapMarkedAlt),
labelText: "Address",
hintText: "Address",
controller: _bspBusinessLegalAddress,
validator: (val) =>
Validators.validateRequired(val, "Address"),
);
}
Widget _buildServicetype() {
return FormBuilder(
autovalidate: autovalidate,
child: FormBuilderCustomField(
attribute: "Select Address",
validators: [FormBuilderValidators.required()],
formField: FormField(
builder: (FormFieldState<dynamic> field) {
return InputDecorator(
decoration: InputDecoration(
prefixIcon: Icon(Icons.business_center),
errorText: field.errorText,
),
isEmpty: _typeValue == [],
child: new DropdownButtonHideUnderline(
child: DropdownButton(
hint: Text("Service Type"),
isExpanded: true,
items: [
"Normal",
"Urgent",
"Emergency",
].map((option) {
return DropdownMenuItem(
child: Text("$option"),
value: option,
);
}).toList(),
value: field.value,
onChanged: (value) {
field.didChange(value);
_serviceType = value;
},
),
),
);
},
)),
);
}
Widget content(BuildContext context, AddWalkinServiceDetailViewModel awsdVm) {
var colorStyles = Theming.colorstyle(context);
Orientation orientation = MediaQuery.of(context).orientation;
return Scaffold(
backgroundColor: colorStyles['primary'],
appBar: AppBar(
elevation: 0,
title: Text("Service Details"),
centerTitle: true,
),
bottomNavigationBar: Container(
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
label: Text('Search'),
color: colorStyles["primary"],
textColor: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {
setState(() {
autovalidate = true;
});
if (_formkey.currentState.validate()) {
List<ServicePicture> id1Images = [];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ServiceProviderMapScreen(
addWalkinModel: model,
),
),
);
}
}
),
],
),
),
body: FadeTransition(
opacity: animation,
child: Container(
child: Form(
autovalidate: autovalidate,
key: _formkey,
child: Stack(
children: <Widget>[
SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_builddate(),
_buildflexible(),
],
),
),
)
],
),
),
),
),
);
}
#override
Widget build(BuildContext context) {
return new StoreConnector<AppState, AddWalkinServiceDetailViewModel>(
converter: (Store<AppState> store) =>
AddWalkinServiceDetailViewModel.fromStore(store),
builder: (BuildContext context, AddWalkinServiceDetailViewModel awsdVm) =>
content(context, awsdVm),
);
}
}
You should be using FormBuilderDropdown instead. This is included in flutter_form_builder.
DropdownButtonHideUnderline(
child: FormBuilderDropdown(
name: 'dropdown'
hint: Text("Service Type"),
isExpanded: true,
items: [
"Normal",
"Urgent",
"Emergency",
].map((option) {
return DropdownMenuItem(
child: Text("$option"),
value: option,
);
}).toList(),,
),
),
Using this, the dropdown value can be extracted by calling it from the Map GlobalKey<FormState>.currentState.value using the name set earlier as the key.
_formKey.currentState.value['dropdown']