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(),
],
),
);
}
}
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 have integrated flutter mobile app with laravel api and I am not able to navigate to next page upon login.
In debug console
D/InputMethodManager(14467): view is not EditText
D/InputMethodManager(14467): prepareNavigationBarInfo() DecorView#fac6bd9[MainActivity]
D/InputMethodManager(14467): getNavigationBarColor() -855310
D/InputMethodManager(14467): SSI - flag : 0 Pid : 14467 view : com.example.FYPApp
D/InputMethodManager(14467): view is not EditText
D/InputMethodManager(14467): prepareNavigationBarInfo() DecorView#fac6bd9[MainActivity]
D/InputMethodManager(14467): getNavigationBarColor() -855310
D/InputMethodManager(14467): SSI - flag : 0 Pid : 14467 view : com.example.FYPApp
D/InputMethodManager(14467): view is not EditText
D/InputMethodManager(14467): prepareNavigationBarInfo() DecorView#fac6bd9[MainActivity]
D/InputMethodManager(14467): getNavigationBarColor() -855310
D/InputMethodManager(14467): SSI - flag : 0 Pid : 14467 view : com.example.FYPApp
D/InputMethodManager(14467): view is not EditText
D/InputMethodManager(14467): prepareNavigationBarInfo() DecorView#fac6bd9[MainActivity]
D/InputMethodManager(14467): getNavigationBarColor() -855310
I/ViewRootImpl#f6eec95[MainActivity](14467): ViewPostIme pointer 0
I/ViewRootImpl#f6eec95[MainActivity](14467): ViewPostIme pointer 1
I/ViewRootImpl#f6eec95[MainActivity](14467): ViewPostIme pointer 0
I/ViewRootImpl#f6eec95[MainActivity](14467): ViewPostIme pointer 1
Flutter Login Code
class _HomePageState extends State<HomePage> {
bool _isHidden = true;
GlobalKey<FormState> _form = GlobalKey<FormState>();
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
Future<void> signIn(String email, pass) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
Map data = {'email': email, 'password': pass};
var jsonResponse;
var response = await http.post("http://192.168.166.61:8000/api/auth/login",
headers: {'Accept': 'application/json'}, body: data);
jsonResponse = json.decode(response.body);
if (response.statusCode == 200) {
if (jsonResponse != null) {
setState(() {});
sharedPreferences.setString('Token', jsonResponse['token']);
sharedPreferences.setString('Email', jsonResponse['email']);
sharedPreferences.setString('Name', jsonResponse['name']);
sharedPreferences.setInt('ID', jsonResponse['id']);
//sharedPreferences.setString("token", jsonResponse['token']);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PrivilegeActivity(),
),
);
}
} else {
setState(() {});
print(response.body);
}
}
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Form(
key: _form,
child: Container(
width: 500,
height: 600,
margin: EdgeInsets.fromLTRB(0.0, 120.0, 0.0, 0.0),
padding: EdgeInsets.all(5),
alignment: Alignment.center,
child: Column(
children: <Widget>[
Image.asset(
'assets/cstlogo.png',
width: 180,
height: 180,
),
Container(
margin: EdgeInsets.fromLTRB(0.0, 30.0, 0.0, 35),
child: Text(
'Log in',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30,
fontFamily: 'PTSerif',
),
),
),
Container(
height: 65,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.black,
width: 1.0,
),
borderRadius: BorderRadius.circular(15.0),
),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TextFormField(
controller: emailController,
validator: (val) {
if (val.isEmpty) return 'please enter emailID';
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
labelText: ' Email ID',
icon: Icon(Icons.email),
labelStyle:
TextStyle(fontFamily: 'PTSerif', fontSize: 20),
),
),
),
//),
),
),
Container(
height: 65,
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.black,
width: 1.0,
),
borderRadius: BorderRadius.circular(15.0),
),
child: Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: TextFormField(
controller: passwordController,
obscureText: _isHidden,
validator: (val) {
if (val.isEmpty) return 'please enter the password';
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
labelText: 'Password',
icon: Icon(Icons.lock),
labelStyle:
TextStyle(fontFamily: 'PTSerif', fontSize: 20),
suffix: InkWell(
onTap: _togglePasswordView,
child: Icon(
_isHidden
? Icons.visibility
: Icons.visibility_off,
),
),
),
),
),
),
),
Container(
height: 50,
width: 120,
margin: EdgeInsets.fromLTRB(0.0, 30.0, 0.0, 0.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.lightBlueAccent),
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
side: BorderSide(color: Colors.black))),
),
onPressed: //emailController.text == "" || passwordController.text == "" ? null :
() {
//setState(() {});
_form.currentState.validate();
signIn(emailController.text, passwordController.text);
},
child: Text(
'log In',
style: TextStyle(
fontSize: 20,
fontFamily: 'PTSerif',
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
),
),
);
}
void _togglePasswordView() {
setState(() {
_isHidden = !_isHidden;
});
}
}
Laravel Login COntroller Code
public function login(Request $request){
$fields = $request->validate([
'email' => 'required|string',
'password' => 'required|string'
]);
//chehck email
$user = User::where('email', $fields['email'])->first();
//chechk password
if(!$user || !Hash::check($fields['password'], $user->password)){
return response([
'message' => 'Bad credintials'
], 401);
}
$token = $user->createToken('myapptoken');//->accessToken;
$user->token = $token->accessToken;
return response($user, 201);
}
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));
}
}),
],
)));
}
}
How can I add validations to the username password when we click on the submit button.
I have created 2 different classes for Widget _buildUserNameTF() and Widget _buildPasswordTF()
when we click on Widget _buildLoginBtn() the validation must be done onWidget _buildUserNameTF() and Widget _buildPasswordTF()
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_app/utilities/constants.dart';
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => new _LoginPageState();
// State<StatefulWidget> createState() {
// return _LoginPageState();
// }
}
class _LoginPageState extends State<LoginPage> {
final scaffoldKey = new GlobalKey<ScaffoldState>();
final formKey = new GlobalKey<FormState>();
// FormType _formType = FormType.login;
String _userName = "";
String _password = "";
void validateAndSave() {
final form = formKey.currentState;
if (form.validate()) {
form.save();
// performLogin();
}
}
void performLogin() {
final snackbar = new SnackBar(
content: new Text("Username : $_userName, password : $_password"),
);
scaffoldKey.currentState.showSnackBar(snackbar);
}
Widget _buildUserNameTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Username',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
keyboardType: TextInputType.text,
key: formKey,
autovalidate: _autoValidate,
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.account_circle,
color: Colors.white,
),
hintText: 'Enter your Username',
hintStyle: kHintTextStyle,
),
validator: (value) {
return value.isEmpty ? 'Username is Required.' : null;
},
onSaved: (value) {
return _userName = value;
},
),
),
],
);
}
Widget _buildPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
obscureText: true,
key: formPassKey,
autovalidate: _autoValidate,
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.lock,
color: Colors.white,
),
hintText: 'Enter your Password',
hintStyle: kHintTextStyle,
),
validator: (String value) {
if (value.isEmpty) {
return 'Password is Required.';
}
if (value.length < 6) {
return 'Password too short.';
}
return null;
// return value.isEmpty ? 'Password is Required.' : null;
// || value.length < 6 ? 'Password too short' : null;
},
onSaved: (String value) {
return _password = value;
},
// validator: (val) =>
// val.length < 6 ? 'Password too short' : null,
// onSaved: (val) => _password = val,
),
),
],
);
}
Widget _buildLoginBtn() {
return Container(
padding: EdgeInsets.symmetric(vertical: 25.0),
width: double.infinity,
child: Form(
child: RaisedButton(
elevation: 5.0,
onPressed: (
){
validateAndSave();
},
// => print('Login Button Pressed'),
padding: EdgeInsets.all(15.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
color: Colors.white,
child: Text(
'LOGIN',
style: TextStyle(
color: Color(0xFF527DAA),
letterSpacing: 1.5,
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
),
),
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF73AEF5),
Color(0xFF61A4F1),
Color(0xFF478DE0),
Color(0xFF398AE5),
],
stops: [0.1, 0.4, 0.7, 0.9],
),
),
),
Container(
height: double.infinity,
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(
horizontal: 40.0,
vertical: 120.0,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// key: formKey,
children: <Widget>[
Text(
'Sign In',
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 30.0),
_buildUserNameTF(),
SizedBox(
height: 30.0,
),
_buildPasswordTF(),
_buildLoginBtn(),
],
),
),
)
],
),
),
),
);
}
}
I tried the following as well but the output interfaces runs like this
You can copy paste run full code below
Step 1: You can remove formKey in TextFormField
TextFormField(
keyboardType: TextInputType.text,
//key: formKey,
Step 2: Wrap Column with Form and provide formKey
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Sign In',
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
final kHintTextStyle = TextStyle(
color: Colors.white54,
fontFamily: 'OpenSans',
);
final kLabelStyle = TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
);
final kBoxDecorationStyle = BoxDecoration(
color: Color(0xFF6CA8F1),
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 6.0,
offset: Offset(0, 2),
),
],
);
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => new _LoginPageState();
// State<StatefulWidget> createState() {
// return _LoginPageState();
// }
}
class _LoginPageState extends State<LoginPage> {
final scaffoldKey = new GlobalKey<ScaffoldState>();
final formKey = new GlobalKey<FormState>();
// FormType _formType = FormType.login;
String _userName = "";
String _password = "";
void validateAndSave() {
final form = formKey.currentState;
if (form.validate()) {
form.save();
// performLogin();
}
}
void performLogin() {
final snackbar = new SnackBar(
content: new Text("Username : $_userName, password : $_password"),
);
scaffoldKey.currentState.showSnackBar(snackbar);
}
Widget _buildUserNameTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Username',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
//decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
keyboardType: TextInputType.text,
//key: formKey,
autovalidate: false,
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.account_circle,
color: Colors.white,
),
hintText: 'Enter your Username',
hintStyle: kHintTextStyle,
),
validator: (value) {
return value.isEmpty ? 'Username is Required.' : null;
},
onSaved: (value) {
return _userName = value;
},
),
),
],
);
}
Widget _buildPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
obscureText: true,
//key: formPassKey,
autovalidate: false,
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.lock,
color: Colors.white,
),
hintText: 'Enter your Password',
hintStyle: kHintTextStyle,
),
validator: (String value) {
if (value.isEmpty) {
return 'Password is Required.';
}
if (value.length < 6) {
return 'Password too short.';
}
return null;
// return value.isEmpty ? 'Password is Required.' : null;
// || value.length < 6 ? 'Password too short' : null;
},
onSaved: (String value) {
return _password = value;
},
// validator: (val) =>
// val.length < 6 ? 'Password too short' : null,
// onSaved: (val) => _password = val,
),
),
],
);
}
Widget _buildLoginBtn() {
return Container(
padding: EdgeInsets.symmetric(vertical: 25.0),
width: double.infinity,
child: Form(
child: RaisedButton(
elevation: 5.0,
onPressed: () {
validateAndSave();
},
// => print('Login Button Pressed'),
padding: EdgeInsets.all(15.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
color: Colors.white,
child: Text(
'LOGIN',
style: TextStyle(
color: Color(0xFF527DAA),
letterSpacing: 1.5,
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
),
),
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF73AEF5),
Color(0xFF61A4F1),
Color(0xFF478DE0),
Color(0xFF398AE5),
],
stops: [0.1, 0.4, 0.7, 0.9],
),
),
),
Container(
height: double.infinity,
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(
horizontal: 40.0,
vertical: 120.0,
),
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// key: formKey,
children: <Widget>[
Text(
'Sign In',
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 30.0),
_buildUserNameTF(),
SizedBox(
height: 30.0,
),
_buildPasswordTF(),
_buildLoginBtn(),
],
),
),
),
)
],
),
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LoginPage(),
);
}
}
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),
),