Conditional statement for DropdownButtonFormFields in registeration form - flutter

Still a newbie with flutter and was wondering if someone could help me with a problem I'm having. I am trying to create a registeration form with email, password, password confirmation, a county and a zip code. (County and zip code forms are the drop down button form fields) I have successfully coded all else except for the zip code drop down. I would need it to be conditional on the county selection. (In a way that if I select a specific county in cali, it would only display that selected county's zip codes and nothing else). Also if someone would know a quick fix to make the dropdown button form fields empty unless clicked on. My current adaptation on it isn't very functional, since you can just leave the option unanswered, when it's supposed to be mandatory. Thank you in advance :)
Existing code below
(I only have the string for one county zip codes) (Also deleted the irrelevant firebase related code for this post)
class RegisterPage extends StatefulWidget {
const RegisterPage({Key? key}) : super(key: key);
#override
State<RegisterPage> createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
// dropdown area
_MyFormStateArea(){
selectedArea = dropdownListArea[0];
}
var selectedArea = '';
final dropdownListArea = <String>['', 'LA', 'San Francisco'...'Santa Barbara'];
// dropdown zipcode
_MyFormStateZip(){
selectedZip = dropdownListZip[0];
}
var selectedZip = '';
final dropdownListZip = <String>['', '90001', '90002', '90003',..., '91609'];
// editing Controller
final emailEditingController = new TextEditingController();
final passwordEditingController = new TextEditingController();
final confirmPasswordEditingController = new TextEditingController();
#override
Widget build(BuildContext context) {
// email field
final emailField = TextFormField(
autofocus: false,
controller: emailEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty) {
return ("Please enter email.");
}
// reg expression for email validation
if (!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]")
.hasMatch(value)) {
return ("Please enter a working email.");
}
return null;
},
onSaved: (value) {
emailEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.mail_outline_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)
),
),
);
// password field
final passwordField = TextFormField(
autofocus: false,
controller: passwordEditingController,
obscureText: true,
validator: (value) {
RegExp regex = new RegExp(r'^.{6,}$');
if (value!.isEmpty) {
return ("A password required.");
}
if(!regex.hasMatch(value)) {
return ("Please enter other password (Min. 6 characters)");
}
},
onSaved: (value) {
passwordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
));
// confirm password field
final confirmPasswordField = TextFormField(
autofocus: false,
controller: confirmPasswordEditingController,
obscureText: true,
validator: (value)
{
if(confirmPasswordEditingController.text != passwordEditingController.text)
{
return "Passwords don't match";
}
return null;
},
onSaved: (value) {
confirmPasswordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password again",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)
),
),
);
// area dropdown
final areaField = DropdownButtonFormField(
value: selectedArea,
items: dropdownListArea.map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedArea = value;
}
});
},
decoration: InputDecoration(
labelText: 'County',
prefixIcon: Icon(Icons.location_city_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);
// zip code field
final zipCodeField = DropdownButtonFormField(
value: selectedZip,
items: dropdownListZip.map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedZip = value;
}
});
},
decoration: InputDecoration(
labelText: 'Zip Code',
prefixIcon: Icon(Icons.location_on_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);
// sign up button
final signUpButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(30),
color: Colors.white,
child: MaterialButton(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signUp(emailEditingController.text, passwordEditingController.text);
},
child: Text("Sign Up", textAlign: TextAlign.center,
style: TextStyle(fontSize: 20,
color: Colors.lightBlue[900],
fontWeight: FontWeight.bold)
),
),
);
return Scaffold(
backgroundColor: Color(0xFFAED8E6),
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => FrontPage()));
},
icon: Icon(Icons.arrow_back),
color: Colors.lightBlue[900],
),
),
body: Center(
child: SingleChildScrollView(
child: Container(
color: Color(0xFFAED8E6),
child: Padding(
padding: const EdgeInsets.fromLTRB(36, 20, 36, 30),
child: Form(
key: _formKey,
child:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 170,
child: Image.asset("assets/AR_logoBold.png",
fit: BoxFit.contain
)),
SizedBox(height: 40,),
emailField,
SizedBox(height: 25,),
passwordField,
SizedBox(height: 25,),
confirmPasswordField,
SizedBox(height: 25,),
areaField,
SizedBox(height: 25,),
zipCodeField,
SizedBox(height: 35,),
signUpButton,
SizedBox(height: 15,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("You already own an account? "),
GestureDetector(onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => LoginPage()));
},
child: Text("Login",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Colors.lightBlue[900])
),)
],
)
],
)),
),
),
),
),
);
}
}

First you should initalize the selectedArea and selectedZip with the first Entry of your List: = dropdownListZip.first and the first entry should not be an empty String
To get only zips that belong to the choosen area you need to know them. At the moment you have two independent lists.
Better you use a map like:
Map<String, List<String>> zipmap = Map('LA': ['9000','9001','9002], 'San Francisco': ['9003', '9004']);
Than you can only display zips that belong to the area quite easy.
Take a look at: Flutter Documentation for Map
Map<String, List<String>> zipmap = Map('LA': ['9000','9001','9002], 'San Francisco': ['9003', '9004']);
final areaField = DropdownButtonFormField(
value: selectedArea,
items: zipmap.keys.toList().map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedArea = value;
}
});
},
decoration: InputDecoration(
labelText: 'County',
prefixIcon: Icon(Icons.location_city_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);
// zip code field
final zipCodeField = DropdownButtonFormField(
value: selectedZip,
items: zipmap[selectedArea].map((e) =>
DropdownMenuItem(value: e, child: Text(e),)).toList(),
onChanged: (String? value) {
setState(() {
if (value != null) {
selectedZip = value;
}
});
},
decoration: InputDecoration(
labelText: 'Zip Code',
prefixIcon: Icon(Icons.location_on_outlined),
contentPadding: EdgeInsets.fromLTRB(20, 10, 0, 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
)
);

Related

Error when focussing on next Focus in Flutter

If I click away from a TextField and then back on it and want to focus on the next TextField (using FocusScope.of(context).nextFocus()) by hitting enter on the software keyboard I get this error:
Exception has occurred.
_AssertionError ('package:flutter/src/widgets/focus_manager.dart': Failed assertion: line 790 pos 7: 'context != null': Tried to get the bounds of a focus node that didn't have its context set yet.
The context needs to be set before trying to evaluate traversal policies. Setting the context is typically done with the attach method.)
This is my code:
import 'package:quizlet/api/convert_json.dart';
import 'package:quizlet/style.dart';
class CreateQuiz extends StatefulWidget {
const CreateQuiz({super.key});
#override
State<CreateQuiz> createState() => _CreateQuizState();
}
class _CreateQuizState extends State<CreateQuiz> {
int wordCount = 3;
List errorDefinitions = [false, false, false];
List errorAnswers = [false, false, false];
bool errorTitle = false;
bool errorDescription = false;
final List definitions = [
TextEditingController(),
TextEditingController(),
TextEditingController()
];
final List answers = [
TextEditingController(),
TextEditingController(),
TextEditingController()
];
final title = TextEditingController();
final description = TextEditingController();
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
final brightness = MediaQuery.of(context).platformBrightness;
bool darkMode = brightness == Brightness.dark;
final hintColor = darkMode ? Colors.white : Colors.black;
return Scaffold(
appBar: AppBar(
title: const Text("Create Quiz"),
actions: [
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.white,
),
onPressed: () {
onPressed();
},
child: Text(
"Done",
style: TextStyle(fontSize: height / 55),
),
),
],
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView(
children: [
SizedBox(
height: height / 40,
),
TextField(
onSubmitted: (value) {
FocusScope.of(context).nextFocus();
},
onChanged: (value) {
setState(() {
errorTitle = false;
});
},
textInputAction: TextInputAction.next,
onEditingComplete: () {},
keyboardType: TextInputType.multiline,
controller: title,
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(10.0),
hintStyle: TextStyle(
color: errorTitle ? Colors.red : hintColor,
),
hintText: errorTitle ? "Title can't be blank" : "Title",
border: const OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: errorTitle ? Colors.red : color1,
width: 2.0,
),
),
),
),
const SizedBox(
height: 5,
),
TextField(
onSubmitted: (value) {
FocusScope.of(context).nextFocus();
},
onChanged: (value) {
setState(() {
errorDescription = false;
});
},
textInputAction: TextInputAction.newline,
onEditingComplete: () {},
controller: description,
maxLines: null,
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(10.0),
hintText: errorDescription
? "Description can't be blank"
: "Description",
hintStyle: TextStyle(
color: errorDescription ? Colors.red : hintColor,
),
border: const OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: errorDescription ? Colors.red : color1,
width: 2.0,
),
),
),
),
SizedBox(
height: height / 20,
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: wordCount,
itemBuilder: (BuildContext context, int i) {
return Column(
children: [
TextField(
onSubmitted: (value) {
FocusScope.of(context).nextFocus();
},
onChanged: (value) {
setState(() {
errorDefinitions[i] = false;
});
},
textInputAction: TextInputAction.next,
onEditingComplete: () {},
autocorrect: false,
controller: definitions[i],
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(10.0),
hintStyle: TextStyle(
color: errorDefinitions[i] ? Colors.red : hintColor,
),
hintText: errorDefinitions[i]
? "Definition can't be blank"
: "Definition",
border: const OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: errorDefinitions[i] ? Colors.red : color1,
width: 2.0,
),
),
),
),
const SizedBox(
height: 5,
),
TextField(
onSubmitted: (value) {
setState(() {
if (definitions[i].text != "" &&
answers[i].text != "") {
if (i + 2 >= wordCount) {
wordCount++;
definitions.add(TextEditingController());
answers.add(TextEditingController());
errorAnswers.add(false);
errorDefinitions.add(false);
}
FocusScope.of(context).nextFocus();
}
});
},
onChanged: (value) {
setState(() {
errorAnswers[i] = false;
});
},
textInputAction: TextInputAction.next,
onEditingComplete: () {},
autocorrect: false,
controller: answers[i],
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(10.0),
hintStyle: TextStyle(
color: errorAnswers[i] ? Colors.red : hintColor,
),
hintText: errorAnswers[i]
? "Answer can't be blank"
: "Answer",
border: const OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: errorAnswers[i] ? Colors.red : color1,
width: 2.0,
),
),
),
),
SizedBox(
height: height / 50,
),
],
);
},
),
],
),
),
),
);
}```

Exception caught by gesture 'then' was called on null

I faced this error when I tried to insert image
"The following NoSuchMethodError was thrown while handling a gesture:
The method 'then' was called on null.
Receiver: null
Tried calling: then(Closure: (dynamic) => Null)"
Below is my code. Hope someone can help me with it. I have no idea how to solve it. Thank you.
// ignore_for_file: import_of_legacy_library_into_null_safe, unrelated_type_equality_checks
import 'dart:io';
import 'package:dparking/model/user_model.dart';
import 'package:dparking/screens/home_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_picker/image_picker.dart';
class RegistrationScreen extends StatefulWidget {
const RegistrationScreen({Key? key}) : super(key: key);
#override
State<RegistrationScreen> createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
final _auth = FirebaseAuth.instance;
// form key
final _formKey = GlobalKey<FormState>();
// editing Controller
final nameEditingController = TextEditingController();
final emailEditingController = TextEditingController();
final passwordEditingController = TextEditingController();
final confirmPasswordEditingController = TextEditingController();
final phoneNumberEditingController = TextEditingController();
XFile? _logo;
final ImagePicker _picker = ImagePicker();
#override
Widget build(BuildContext context) {
// Name field
final nameField = TextFormField(
autofocus: false,
controller: nameEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
RegExp regex = RegExp(r'^.{3,}$');
if(value!.isEmpty){
return ("Name cannot be Empty");
}
if(!regex.hasMatch(value))
{
return ("Enter Valid Name(Min. 3 Character");
}
return null;
},
onSaved: (value)
{
nameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.account_circle),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
// Email field
final emailField = TextFormField(
autofocus: false,
controller: emailEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value)
{
if(value!.isEmpty)
{
return ("Please Enter Your Email");
}
// reg expression for email validation
if(!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]").hasMatch(value))
{
return("Please Enter a valid email");
}
return null;
},
onSaved: (value)
{
emailEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.mail),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
// Password field
final passwordField = TextFormField(
autofocus: false,
controller: passwordEditingController,
obscureText: true,
validator: (value) {
RegExp regex = RegExp(r'^.{6,}$');
if(value!.isEmpty){
return ("Password is required for login");
}
if(!regex.hasMatch(value))
{
return ("Enter Valid Password(Min. 6 Character");
}
return null;
},
onSaved: (value)
{
passwordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.vpn_key),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
// Confirm Password field
final confirmPasswordField = TextFormField(
autofocus: false,
controller: confirmPasswordEditingController,
obscureText: true,
validator: (value)
{
if(confirmPasswordEditingController.text.length !=
passwordEditingController.text){
return "Password Does Not Match";
}
return null;
},
onSaved: (value)
{
confirmPasswordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.vpn_key),
contentPadding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Confirm Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
//signup button
final signupButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(30),
color: Colors.redAccent,
child: MaterialButton(
padding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signUp(emailEditingController.text, passwordEditingController.text);
},
child: const Text("SignUp", textAlign: TextAlign.center,
style: TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold,),
),
),
);
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.red),
onPressed: (){
Navigator.of(context).pop();
},
),
),
body: Center(
child: SingleChildScrollView(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 200,
width: 300,
child: Image.asset("assets/images/DParking.png",
fit: BoxFit.contain,
color: Colors.black,
),
),
nameField,
const SizedBox(height: 30),
emailField,
const SizedBox(height: 30),
passwordField,
const SizedBox(height: 30),
confirmPasswordField,
const SizedBox(height: 30),
InkWell(
onTap: (){
_pickImage().then((value){ //i think the error is here
setState((){
_logo = value;
});
});
},
child: Card(
elevation: 4,
child: _logo==null ? const SizedBox(
height: 100,
width: 250,
child: Center(
child: Text('Insert Identification Card'),
),
):SizedBox(
height: 100,
width: 250,
child: Image.file(File(_logo!.path),)
),
),
),
const SizedBox(height: 30),
signupButton,
const SizedBox(height: 30),
],
),
),
),
),
),
)
);
}
void signUp(String email, String password) async
{
if (_formKey.currentState!.validate()) {
await _auth
.createUserWithEmailAndPassword(email: email, password: password)
.then((value) => {postDetailsToFirestore()})
.catchError((e) {
Fluttertoast.showToast(msg: e!.message);
});
}
}
postDetailsToFirestore() async {
// call firestore
//call user model
//send value
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
User? user = _auth.currentUser;
UserModel userModel = UserModel();
userModel.email = user!.email;
userModel.uid = user.uid;
userModel.name = nameEditingController.text;
await firebaseFirestore
.collection("users")
.doc(user.uid)
.set(userModel.toMap());
Fluttertoast.showToast(msg: "Account created successfully");
Navigator.pushAndRemoveUntil(
(context),
MaterialPageRoute(builder: (context) => const HomeScreen()),
(route) => false);
}
}
_pickImage() {
}

Flutter - Text forms not moving above the keyboard upon opening

I am fairly new to flutter and dart as a whole and i have been creating an application that interacts with firebase, this is the code for my registration screen. When clicking on a text input field the keyboard ends up blocking the forms and you cannot see what you are entering... I have tried many things such as singlechildscroll view and resizeToAvoidBottomInset and nothing seems to be affecting it. Anyone have any idea?
Register page:
class RegistrationPage extends StatefulWidget{
const RegistrationPage({Key? key}) : super(key: key);
#override
_RegistrationPageState createState() => _RegistrationPageState();
}
class _RegistrationPageState extends State<RegistrationPage> {
final _auth = FirebaseAuth.instance;
//our form key
final _formKey = GlobalKey<FormState>();
//editing controllers
final firstNameEditingController = new TextEditingController();
final lastNameEditingController = new TextEditingController();
final emailEditingController = new TextEditingController();
final passwordEditingController = new TextEditingController();
final confirmPasswordEditingController = new TextEditingController();
final cityEditingController = new TextEditingController();
#override
Widget build(BuildContext context) {
//firstname Field
final firstNameField = TextFormField(
autofocus: false,
controller: firstNameEditingController,
keyboardType: TextInputType.name,
validator: (value)
{
RegExp regEx = new RegExp(r'^.{2,}$');
if(value!.isEmpty)
{
return("First Name cannot be empty");
}
if(!regEx.hasMatch(value))
{
return("Enter valid name(min 2 characters)");
}
return null;
},
onSaved: (value) {
firstNameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.face),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "First name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
));
//Last name Field
final lastNameField = TextFormField(
autofocus: false,
controller: lastNameEditingController,
keyboardType: TextInputType.name,
validator: (value)
{
RegExp regEx = new RegExp(r'^.{2,}$');
if(value!.isEmpty)
{
return("Last Name cannot be empty");
}
return null;
},
onSaved: (value) {
lastNameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.face),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Last name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
));
//email Field
final emailField = TextFormField(
autofocus: false,
controller: emailEditingController,
keyboardType: TextInputType.text,
validator: (value)
{
if(value!.isEmpty)
{
return("Please enter your email");
}
//email validation
if(!RegExp("^[a-zA-Z0-9+_.-]+#[a-zA-Z0-9.-]+.[a-z]").hasMatch(value))
{
return("Please enter a valid email");
}
},
onSaved: (value) {
emailEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.account_circle),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Email address",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
));
//City
final cityField = TextFormField(
autofocus: false,
controller: cityEditingController,
keyboardType: TextInputType.text,
validator: (value)
{
RegExp regEx = new RegExp(r'^.{2,}$');
if(value!.isEmpty)
{
return("City cannot be empty");
}
return null;
},
onSaved: (value) {
cityEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.location_on),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "City",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
));
//password Field
final passwordField = TextFormField(
autofocus: false,
controller: passwordEditingController,
obscureText: true,
validator: (value)
{
RegExp regEx = new RegExp(r'^.{6,}$');
if(value!.isEmpty)
{
return("Password is required!");
}
if(!regEx.hasMatch(value))
{
return("Enter valid password(Min. 6 characters)");
}
},
onSaved: (value) {
passwordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
)
);
//Confirm password Field
final confirmPasswordField = TextFormField(
autofocus: false,
controller: confirmPasswordEditingController,
obscureText: true,
validator: (value)
{
if (confirmPasswordEditingController.text != passwordEditingController.text){
return "Passwords do not match";
}
return null;
},
onSaved: (value) {
confirmPasswordEditingController.text = value!;
},
textInputAction: TextInputAction.done,
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: "Confirm Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
)
);
final registerButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(30),
color: Colors.pink,
child: MaterialButton(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signUp(emailEditingController.text, passwordEditingController.text);
},
child: Text("Register", textAlign:TextAlign.center,
style: TextStyle(
fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold),
),
)
);
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.pink),
onPressed:(){
Navigator.of(context).pop();
},
)
),
body: Center(
child: new SingleChildScrollView(
reverse: true,
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 180,
child: Image.asset(
"assets/logo.png",
fit: BoxFit.contain,
)),
SizedBox(height: 30),
firstNameField,
SizedBox(height: 10),
lastNameField,
SizedBox(height: 10),
emailField,
SizedBox(height:10),
cityField,
SizedBox(height: 10),
passwordField,
SizedBox(height: 10),
confirmPasswordField,
SizedBox(height: 10),
registerButton,
],
),
),
)
)
)
)
);
Main.dart
Future<void> main() async { //asynchronous programming, waits for events to happen before producing a result
WidgetsFlutterBinding.ensureInitialized(); //in this case initializes the Firebase waits for a callback
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget { //Used to build application
const MyApp({Key? key}) : super(key: key); //Anything in here runs when the app starts
ThemeData _appTheme() { //The login screen is first to load but this is not in place of main as it is bad practise
final ThemeData base = ThemeData.light(); //Will be used for implementation of light and dark theme
return base.copyWith(
colorScheme: base.colorScheme.copyWith(
primary: travelBlue,
onPrimary: Colors.white,
secondary: travelBlue,
error: travelErrorRed,
),
);
}
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp( //Runs when main.dart is executed
title: 'Login',
theme: _appTheme(),
home: LoginPage(),
);
}
}
try wrapping your column with padding
Padding(
padding: MediaQuery.of(context).viewInsets,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// your entire form widgets here
]
)
)

Flutter show error when Password not match

I want to validate the passwords. The Widget _buildRepeatPasswordTF, has a TextFormField that validates if the value is not equal to the controller from _buildPasswordTF().
Widget _buildPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: < Widget > [
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextField(
controller: _passwordController,
obscureText: true,
style: TextStyle(
color: Color.fromRGBO(0, 128, 128, 1),
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.lock,
color: Color.fromRGBO(0, 128, 128, 1),
),
hintText: 'Password',
hintStyle: kHintTextStyle,
),
),
),
],
);
}
Widget _buildRepeatPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
controller: _repeatPasswordController,
obscureText: true,
style: TextStyle(
color: Color.fromRGBO(0, 128, 128, 1),
fontFamily: 'OpenSans',
),
validator: (value) {
if (value != _passwordController.text) {
return 'The password doesnt match';
}
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.lock,
color: Color.fromRGBO(0, 128, 128, 1),
),
hintText: 'Repeat password',
hintStyle: kHintTextStyle,
),
),
),
],
);
}
Widget _buildSignUpBtn() {
return Container(
padding: EdgeInsets.symmetric(vertical: 25.0),
width: double.infinity,
child: RaisedButton(
elevation: 5.0,
onPressed: () async {
var password = _passwordController.text;
var email = _emailController.text;
var nom = _nameController.text;
var cognoms = _cognomsController.text;
try {
var r = await _provider.attemptSignUp(email, password, nom, cognoms, interessos, sexe, dataNeixement);
if(r['success'] == false) {
displayDialog(context, "Error", r['data']['message']);
}
else {
displayDialog(context, "Registrat", "Verifica el correu.").then((val) {
Navigator.of(context).pop();
});
}
} catch (err) {
displayDialog(context, "Error", err.response.toString());
}
},
padding: EdgeInsets.all(15.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
color: Color.fromRGBO(0, 128, 128, 1),
child: Text(
'Registrar-se',
style: TextStyle(
color: Colors.white,
letterSpacing: 1.5,
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
),
),
),
);
}
You have missed a main Form and GlobalKeys.
Here a complete functional sample:
import 'package:flutter/material.dart';
class Password extends StatefulWidget {
#override
_PasswordState createState() => _PasswordState();
}
class _PasswordState extends State<Password> {
final TextEditingController _password = TextEditingController();
final TextEditingController _confirmPassword = TextEditingController();
final GlobalKey<FormState> _form = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(30),
child: Form(
key: _form,
child: Column(children: <Widget>[
TextFormField(
controller: _password,
validator: (validator) {
if (validator.isEmpty) return 'Empty';
return null;
}),
TextFormField(
controller: _confirmPassword,
validator: (validator) {
if (validator.isEmpty) return 'Empty';
if (validator != _password.text)
return 'The passwords do not match';
return null;
}),
RaisedButton(
child: Text(
'Registrar-se',
),
elevation: 5.0,
onPressed: () async {
_form.currentState.validate();
})
])),
);
}
}
I also have made a validation more sophisticated using RxDart and Streams. Check it out on medium

Validating TextformField with two different key in Flutter

I'm trying to validate two different TextFormFields in two widgets (One for Email, another one for password) with a single _formkey in a flutter. it gave me this error: Multiple widgets used the same GlobalKey. So defined two _formkey but the problem is Flutter form validators don't validate, simultaneously:
class _RegisterState extends State<Register> {
String email = "";
String password = "";
String error = "";
final _formKey1 = GlobalKey<FormState>();
final _formKey2 = GlobalKey<FormState>();
// bool _rememberMe = false;
Widget _buildEmailTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Email',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Form(
key: _formKey1,
child: Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
validator: (value) => value.isEmpty ? "Enter an Email" : null,
onChanged: (value) {
setState(() {
email = value;
});
},
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Enter your Email',
hintStyle: kHintTextStyle,
),
),
),
),
],
);
}
Widget _buildPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Form(
key: _formKey2,
child: Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
validator: (value) =>
value.length < 6 ? "More than 6 Character" : null,
onChanged: (value) {
setState(() {
password = value;
});
},
obscureText: true,
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,
),
),
),
),
],
);
}
and then :
onPressed: () async {
if (_formKey1.currentState.validate() &&
_formKey2.currentState.validate()) {
dynamic result =
await _auth.signUpWithEmailandPassword(email, password);
if (result == null) {
setState(() => error = "Something is wrong");
}
}
},
Just remember that you need one Form Widget above in the widget Tree.
And thus you can use the _formKey to validate multiple TextFormField below in the Widget Tree.
Modified Code
class _RegisterPageState extends State<RegisterPage> {
String email = "";
String password = "";
String error = "";
final _formKey1 = GlobalKey<FormState>();
// final _formKey2 = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Form(
key: _formKey1,
child: Container(
child: Column(
children: [
_buildEmailTF(),
SizedBox(
height: 20,
),
_buildPasswordTF(),
FlatButton(
onPressed: () async {
if (_formKey1.currentState.validate()) {
// dynamic result = await _auth.signUpWithEmailandPassword(
// email, password);
// if (result == null) {
// setState(() => error = "Something is wrong");
// }
print('DOne Working');
}
},
child: Text(
'Done',
))
],
),
),
),
);
}
// bool _rememberMe = false;
Widget _buildEmailTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Email',
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
height: 60.0,
child: TextFormField(
validator: (value) => value.isEmpty ? "Enter an Email" : null,
onChanged: (value) {
setState(() {
email = value;
});
},
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Enter your Email',
),
),
),
],
);
}
Widget _buildPasswordTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
height: 60.0,
child: TextFormField(
validator: (value) =>
value.length < 6 ? "More than 6 Character" : null,
onChanged: (value) {
setState(() {
password = value;
});
},
obscureText: true,
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',
),
),
),
],
);
}
}
I/flutter (24750): DOne Working