So I'm actually pretty new with flutter and this is my first project. Everything went well, until this problem came up.
Recently, I added a stepperBody into my page and in one of the steps there should be a datePicker integrated. Unfortunately, I can't really resolve the problem that is coming up.
I'm constantly getting an "Only static members can be accessed in initializers." error.
Help is appreciated.
I'm using the flutter_datetime_picker plugin.
Here's my code:
class StepperBody extends StatefulWidget {
#override
_StepperBodyState createState() => _StepperBodyState();
}
class _StepperBodyState extends State<StepperBody> {
String _date = "Not set";
int currStep = 0;
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
static MyData data = MyData();
#override
void initState() {
super.initState();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
List<Step> steps = [
Step(
title: const Text('Name',
style: TextStyle(
fontFamily: 'Maax',
fontSize: 20,
),),
//subtitle: const Text('Enter your name'),
isActive: true,
//state: StepState.error,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: Column(
children: <Widget>[
TextFormField(
style: TextStyle(
fontFamily: 'Maax',
fontWeight: FontWeight.w500,
),
focusNode: _focusNode,
keyboardType: TextInputType.text,
autocorrect: false,
onSaved: (String value) {
data.title = value;
},
maxLines: 1,
//initialValue: 'Aseem Wangoo',
validator: (value) {
if (value.isEmpty || value.length < 1) {
return 'Please enter title';
}
},
decoration: InputDecoration(
labelText: 'What is the name of the test?',
hintText: 'Enter a name',
//filled: true,
icon: const FaIcon(FontAwesomeIcons.signature),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid, fontFamily: 'Maax', fontWeight: FontWeight.w500)),
),
],
),
)),
Step(
title: const Text('Date'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[1],
child: Column(
children: <Widget>[
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
elevation: 4.0,
onPressed: () {
DatePicker.showDatePicker(context,
theme: DatePickerTheme(
containerHeight: 210.0,
),
showTitleActions: true,
minTime: DateTime(2000, 1, 1),
maxTime: DateTime(2022, 12, 31), onConfirm: (date) {
print('confirm $date');
_date = '${date.year} - ${date.month} - ${date.day}';
setState(() {});
}, currentTime: DateTime.now(), locale: LocaleType.en);
},
child: Container(
alignment: Alignment.center,
height: 50.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Container(
child: Row(
children: <Widget>[
Icon(
Icons.date_range,
size: 18.0,
color: Colors.teal,
),
Text(
" $_date",
style: TextStyle(
color: Colors.teal,
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
],
),
)
],
),
Text(
" Change",
style: TextStyle(
color: Colors.teal,
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
],
),
),
color: Colors.white,
),
TextFormField(
keyboardType: TextInputType.phone,
autocorrect: false,
validator: (value) {
if (value.isEmpty || value.length < 10) {
return 'Please enter valid number';
}
},
onSaved: (String value) {
data.days = value;
},
maxLines: 1,
decoration: InputDecoration(
labelText: 'Enter your number',
hintText: 'Enter a number',
icon: const Icon(Icons.phone),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
Step(
title: const Text('Email'),
// subtitle: const Text('Subtitle'),
isActive: true,
state: StepState.indexed,
// state: StepState.disabled,
content: Form(
key: formKeys[2],
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.emailAddress,
autocorrect: false,
validator: (value) {
if (value.isEmpty || !value.contains('#')) {
return 'Please enter valid email';
}
},
onSaved: (String value) {
data.words = value;
},
maxLines: 1,
decoration: InputDecoration(
labelText: 'Enter your email',
hintText: 'Enter a email address',
icon: const Icon(Icons.email),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
Step(
title: const Text('Age'),
// subtitle: const Text('Subtitle'),
isActive: true,
state: StepState.indexed,
content: Form(
key: formKeys[3],
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.number,
autocorrect: false,
validator: (value) {
if (value.isEmpty || value.length > 2) {
return 'Please enter valid age';
}
},
maxLines: 1,
onSaved: (String value) {
data.rep = value;
},
decoration: InputDecoration(
labelText: 'Enter your age',
hintText: 'Enter age',
icon: const Icon(Icons.explicit),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
// Step(
// title: const Text('Fifth Step'),
// subtitle: const Text('Subtitle'),
// isActive: true,
// state: StepState.complete,
// content: const Text('Enjoy Step Fifth'))
];
#override
Widget build(BuildContext context) {
void showSnackBarMessage(String message,
[MaterialColor color = Colors.red]) {
Scaffold
.of(context)
.showSnackBar( SnackBar(content: Text(message)));
}
void _submitDetails() {
final FormState formState = _formKey.currentState;
if (!formState.validate()) {
showSnackBarMessage('Please enter correct data');
} else {
formState.save();
print("Name: ${data.title}");
print("Phone: ${data.days}");
print("Email: ${data.words}");
print("Age: ${data.rep}");
showDialog(
context: context,
child: AlertDialog(
title: Text("Details"),
//content: Text("Hello World"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text("Name : " + data.title),
Text("Phone : " + data.days),
Text("Email : " + data.words),
Text("Age : " + data.rep),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
));
}
}
return Container(
child: Form(
key: _formKey,
child: ListView(children: <Widget>[
Stepper(
steps: steps,
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if(formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
// else {
// Scaffold
// .of(context)
// .showSnackBar( SnackBar(content: Text('$currStep')));
// if (currStep == 1) {
// print('First Step');
// print('object' + FocusScope.of(context).toStringDeep());
// }
// }
});
},
onStepCancel: () {
setState(() {
if (currStep > 0) {
currStep = currStep - 1;
} else {
currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
RaisedButton(
child: Text(
'Save details',
style: TextStyle(color: Colors.white),
),
onPressed: _submitDetails,
color: Colors.blue,
),
]),
));
}
}
You can copy paste run full code below
You can move steps definition to build to avoid Only static members can be accessed in initializers and allow _date to change after setState
To avoid known issue of flutter_datetime_picker, I use this git
flutter_datetime_picker:
git:
url: https://github.com/derohimat/flutter_datetime_picker.git
code snippet
#override
Widget build(BuildContext context) {
steps = [
Step(
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
class MyData {
String title;
String days;
String words;
String rep;
MyData({this.title, this.days, this.words, this.rep});
}
class StepperBody extends StatefulWidget {
#override
_StepperBodyState createState() => _StepperBodyState();
}
class _StepperBodyState extends State<StepperBody> {
String _date = "Not set";
int currStep = 0;
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
static MyData data = MyData();
List<GlobalKey<FormState>> formKeys = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>()
];
List<Step> steps = [];
#override
void initState() {
super.initState();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
#override
Widget build(BuildContext context) {
steps = [
Step(
title: const Text(
'Name',
style: TextStyle(
fontFamily: 'Maax',
fontSize: 20,
),
),
//subtitle: const Text('Enter your name'),
isActive: true,
//state: StepState.error,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: Column(
children: <Widget>[
TextFormField(
style: TextStyle(
fontFamily: 'Maax',
fontWeight: FontWeight.w500,
),
focusNode: _focusNode,
keyboardType: TextInputType.text,
autocorrect: false,
onSaved: (String value) {
data.title = value;
},
maxLines: 1,
//initialValue: 'Aseem Wangoo',
validator: (value) {
if (value.isEmpty || value.length < 1) {
return 'Please enter title';
}
},
decoration: InputDecoration(
labelText: 'What is the name of the test?',
hintText: 'Enter a name',
//filled: true,
icon: Icon(Icons.add),
labelStyle: TextStyle(
decorationStyle: TextDecorationStyle.solid,
fontFamily: 'Maax',
fontWeight: FontWeight.w500)),
),
],
),
)),
Step(
title: const Text('Date'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[1],
child: Column(
children: <Widget>[
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
elevation: 4.0,
onPressed: () {
DatePicker.showDatePicker(context,
theme: DatePickerTheme(
containerHeight: 210.0,
),
showTitleActions: true,
minTime: DateTime(2000, 1, 1),
maxTime: DateTime(2022, 12, 31), onConfirm: (date) {
print('confirm $date');
_date = '${date.year} - ${date.month} - ${date.day}';
print('date ${_date}');
setState(() {});
}, currentTime: DateTime.now(), locale: LocaleType.en);
},
child: Container(
alignment: Alignment.center,
height: 50.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
Container(
child: Row(
children: <Widget>[
Icon(
Icons.date_range,
size: 18.0,
color: Colors.teal,
),
Text(
" $_date",
style: TextStyle(
color: Colors.teal,
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
],
),
)
],
),
Text(
" Change",
style: TextStyle(
color: Colors.teal,
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
],
),
),
color: Colors.white,
),
TextFormField(
keyboardType: TextInputType.phone,
autocorrect: false,
validator: (value) {
if (value.isEmpty || value.length < 10) {
return 'Please enter valid number';
}
},
onSaved: (String value) {
data.days = value;
},
maxLines: 1,
decoration: InputDecoration(
labelText: 'Enter your number',
hintText: 'Enter a number',
icon: const Icon(Icons.phone),
labelStyle: TextStyle(
decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
Step(
title: const Text('Email'),
// subtitle: const Text('Subtitle'),
isActive: true,
state: StepState.indexed,
// state: StepState.disabled,
content: Form(
key: formKeys[2],
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.emailAddress,
autocorrect: false,
validator: (value) {
if (value.isEmpty || !value.contains('#')) {
return 'Please enter valid email';
}
},
onSaved: (String value) {
data.words = value;
},
maxLines: 1,
decoration: InputDecoration(
labelText: 'Enter your email',
hintText: 'Enter a email address',
icon: const Icon(Icons.email),
labelStyle: TextStyle(
decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
Step(
title: const Text('Age'),
// subtitle: const Text('Subtitle'),
isActive: true,
state: StepState.indexed,
content: Form(
key: formKeys[3],
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.number,
autocorrect: false,
validator: (value) {
if (value.isEmpty || value.length > 2) {
return 'Please enter valid age';
}
},
maxLines: 1,
onSaved: (String value) {
data.rep = value;
},
decoration: InputDecoration(
labelText: 'Enter your age',
hintText: 'Enter age',
icon: const Icon(Icons.explicit),
labelStyle: TextStyle(
decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
// Step(
// title: const Text('Fifth Step'),
// subtitle: const Text('Subtitle'),
// isActive: true,
// state: StepState.complete,
// content: const Text('Enjoy Step Fifth'))
];
void showSnackBarMessage(String message,
[MaterialColor color = Colors.red]) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
}
void _submitDetails() {
final FormState formState = _formKey.currentState;
if (!formState.validate()) {
showSnackBarMessage('Please enter correct data');
} else {
formState.save();
print("Name: ${data.title}");
print("Phone: ${data.days}");
print("Email: ${data.words}");
print("Age: ${data.rep}");
showDialog(
context: context,
child: AlertDialog(
title: Text("Details"),
//content: Text("Hello World"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text("Name : " + data.title),
Text("Phone : " + data.days),
Text("Email : " + data.words),
Text("Age : " + data.rep),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
));
}
}
return Container(
child: Form(
key: _formKey,
child: ListView(children: <Widget>[
Stepper(
steps: steps,
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if (formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
// else {
// Scaffold
// .of(context)
// .showSnackBar( SnackBar(content: Text('$currStep')));
// if (currStep == 1) {
// print('First Step');
// print('object' + FocusScope.of(context).toStringDeep());
// }
// }
});
},
onStepCancel: () {
setState(() {
if (currStep > 0) {
currStep = currStep - 1;
} else {
currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
RaisedButton(
child: Text(
'Save details',
style: TextStyle(color: Colors.white),
),
onPressed: _submitDetails,
color: Colors.blue,
),
]),
));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "test",),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: StepperBody()),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Related
This is a part of a project regarding feedback forms.
I already manage to create the validation form properly thanks to the answers here in StackOverflow developers.
But the problem is creating this regular expression which seems to not work on the validation form. I found in flutter docs the Iterable but I do not know how can I implement it on the dart page.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class SimpleDialog extends StatelessWidget {
// ignore: prefer_typing_uninitialized_variables
final title;
const SimpleDialog(this.title, {super.key});
#override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Alert'),
content: Text(title),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'))
],
);
}
}
class FeedbackPage extends StatefulWidget {
const FeedbackPage({super.key});
#override
State<FeedbackPage> createState() => _FeedbackPageState();
}
class _FeedbackPageState extends State<FeedbackPage> {
final nameOfuser = TextEditingController();
final emailOfuser = TextEditingController();
final messageOfuser = TextEditingController();
final _formKey = GlobalKey<FormState>();
List<bool> isTypeSelected = [false, false, false, true, true];
#override
Widget build(BuildContext context) {
return Scaffold(
// AppBar para sa taas ng design
appBar: AppBar(
centerTitle: true,
title: const Text(
"PicLeaf",
style: TextStyle(
color: Color.fromRGBO(102, 204, 102, 1.0),
fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
shadowColor: const Color.fromARGB(255, 95, 94, 94),
),
//body of the application
backgroundColor: const Color(0xffeeeeee),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const SizedBox(
height: 20,
),
const Text(
"Feedback",
style: TextStyle(
fontSize: 30.0,
fontFamily: 'RobotoBold',
fontWeight: FontWeight.bold,
color: Color.fromRGBO(102, 204, 102, 1.0)),
),
const Text(
"Give us your feedback!",
style: TextStyle(
fontSize: 18.0,
fontFamily: 'RobotoMedium',
),
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
const SizedBox(height: 16.0),
TextFormField(
controller: nameOfuser,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Name",
border: OutlineInputBorder(),
),
validator: (nameOfuser) {
if (nameOfuser == null || nameOfuser.isEmpty) {
return 'Please enter your Name';
}
return null;
},
),
const SizedBox(height: 8.0),
TextFormField(
controller: emailOfuser,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Email",
border: OutlineInputBorder(),
),
validator: (emailOfuser) {
if (emailOfuser == null || emailOfuser.isEmpty) {
String emailOfuser1 = emailOfuser.toString();
String pattern = r'\w+#\w+\.\w+';
if (RegExp(pattern).hasMatch(emailOfuser1)) {
return 'Please enter your Email Properly';
} else {
return 'Please enter your Email';
}
}
return null;
},
),
const SizedBox(height: 8.0),
TextFormField(
controller: messageOfuser,
maxLines: 6,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
hintText: "Message",
border: OutlineInputBorder(),
),
validator: (messageOfuser) {
if (messageOfuser == null || messageOfuser.isEmpty) {
return 'Please enter your Message';
}
return null;
},
),
const SizedBox(height: 8.0),
MaterialButton(
height: 50.0,
minWidth: double.infinity,
color: const Color.fromRGBO(102, 204, 102, 1.0),
onPressed: () {
if (_formKey.currentState!.validate()) {
showDialog(
context: context,
builder: (BuildContext context) {
return const SimpleDialog(
'Feedback Submitted');
});
Map<String, dynamic> data = {
"Name": nameOfuser.text,
"Email": emailOfuser.text,
"Message": messageOfuser.text,
"Time": FieldValue.serverTimestamp(),
};
setState(() {
nameOfuser.clear();
emailOfuser.clear();
messageOfuser.clear();
});
FirebaseFirestore.instance
.collection("FeedbackMessages")
.add(data);
}
},
child: const Text(
"SUBMIT",
style: TextStyle(
fontFamily: 'RobotoBold',
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
const SizedBox(
height: 10,
),
Container(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 10),
child: const Text(
'Contact Us!',
style: TextStyle(
fontSize: 30,
fontFamily: 'RobotoBold',
color: Color.fromRGBO(102, 204, 102, 1.0)),
textAlign: TextAlign.center,
),
),
Column(
children: <Widget>[
Container(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: TextButton.icon(
// <-- TextButton
onPressed: () {},
icon: const Icon(
Icons.facebook,
color: Colors.black,
size: 35.0,
),
label: const Text(
'facebook.com/picleaf',
style: TextStyle(fontFamily: 'RobotoMedium'),
),
style: TextButton.styleFrom(
foregroundColor: Colors.black,
),
),
),
Container(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: TextButton.icon(
// <-- TextButton
onPressed: () {},
icon: const Icon(
Icons.email,
color: Colors.black,
size: 35.0,
),
label: const Text(
'picleaf#gmail.com',
style: TextStyle(fontFamily: 'RobotoMedium'),
),
style: TextButton.styleFrom(
foregroundColor: Colors.black,
),
)),
],
)
],
),
),
),
],
),
));
}
}
You can use this validator:
validator: (emailOfuser) {
if (emailOfuser == null || emailOfuser.isEmpty) {
return 'Please enter your Email';
} else if (emailOfuser.isNotEmpty) {
String emailOfuser1 = emailOfuser.toString();
String pattern = r'\w+#\w+\.\w+';
if (RegExp(pattern).hasMatch(emailOfuser1) == false) {
return 'Please enter your Email Properly';
}
}
return null;
},
try to implement like this:
import 'package:flutter/material.dart';
class EmailValidationForm extends StatefulWidget {
const EmailValidationForm({Key? key}) : super(key: key);
#override
State<EmailValidationForm> createState() => _EmailValidationFormState();
}
class _EmailValidationFormState extends State<EmailValidationForm> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Email Validation'),
),
body: Form(
key: formKey,
child: Column(
children: [
TextFormField(
autofocus: false,
maxLength: 300,
keyboardType: TextInputType.emailAddress,
autocorrect: false,
validator: (email) {
if (email!.isEmpty) {
return 'required field';
} else if (email.trim().contains(' ')) {
return 'contain space';
} else if (!emailValid(email)) {
return 'invalid email';
}
return null;
},
onSaved: (email) {
return debugPrint(email);
},
),
ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
formKey.currentState!.save();
}
},
child: const Text('Validate')),
],
),
),
);
}
}
bool emailValid(String email) {
final RegExp regex = RegExp(
r"^(([^<>()[\]\\.,;:\s#\']+(\.[^<>()[\]\\.,;:\s#\']+)*)|(\'.+\'))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$");
return regex.hasMatch(email.trim());
}
Warning: Ignoring header X-Firebase-Locale because its value was null.
I'm getting this warning while signing up a user in firebase. When i signup in my app it doesn't get added into firebase?(I'm working on flutter in VS Code). Code for my Signup Page is being written below:
class Signup extends StatefulWidget {
Signup ({ Key? key }) : super(key: key);
#override
_SignupState createState() => _SignupState();
}
class _SignupState extends State<Signup> {
final _formKey = GlobalKey<FormState>();
var email = " ";
var password = " ";
var confirmPassword = " ";
final emailController = TextEditingController();
final passwordController = TextEditingController();
final confirmPasswordController = TextEditingController();
#override
void dispose()
{
emailController.dispose();
passwordController.dispose();
confirmPasswordController.dispose();
super.dispose();
}
registration() async{
if(password == confirmPassword)
{
try{
await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password);
}catch(e){}
}
else{
print("Password doesn't match");
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('User Signup'),
),
body : Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30),
child: ListView(
children: [
Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
autofocus: false,
decoration: InputDecoration(
labelText: 'Email: ',
labelStyle: TextStyle(fontSize: 20.0),
border: OutlineInputBorder(),
errorStyle:
TextStyle(color: Colors.redAccent,
fontSize: 15),
),
controller: emailController,
validator: (value)
{
if(value==null || value.isEmpty)
{
return 'Please Enter Email';
}
else if(!value.contains('#'))
{
return 'Please Enter Valid Email';
}
return null;
},
)
),
Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
autofocus: false,
obscureText: true,
decoration: InputDecoration(
labelText: 'Password: ',
labelStyle: TextStyle(fontSize: 20.0),
border: OutlineInputBorder(),
errorStyle:
TextStyle(color: Colors.redAccent,
fontSize: 15),
),
controller: passwordController,
validator: (value)
{
if(value==null || value.isEmpty)
{
return 'Please Enter Password';
}
return null;
},
)
),
Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
autofocus: false,
obscureText: true,
decoration: InputDecoration(
labelText: 'Confirm Password: ',
labelStyle: TextStyle(fontSize: 20.0),
border: OutlineInputBorder(),
errorStyle:
TextStyle(color: Colors.redAccent,
fontSize: 15),
),
controller: confirmPasswordController,
validator: (value)
{
if(value==null || value.isEmpty)
{
return 'Please Enter Password';
}
return null;
},
)
),
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
if(_formKey.currentState!.validate())
{
setState(() {
email = emailController.text;
password =passwordController.text;
confirmPassword = confirmPasswordController.text;
});
}
registration();
},
child: Text(
'Sign Up',
style: TextStyle(color: Colors.white, fontSize: 20),
)
)
],
),
),
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:[
Text("Already have an Account? "),
TextButton(
onPressed: ()=>{
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder:
(context, animation1, animation2)
=>LoginPage(),
transitionDuration: Duration(seconds:0),
)
),
},
child: Text('Login')
)
]
)
)
],
)
)
)
);
}
}
I'm expecting to get a user added in firebase after signing up through my app.
I want to create two checkbox next to each other and when one of them is checked, the other one be unchecked but I don`t know how to do that in flutter, so I'll be wonderful if someone could help me.
here is my codes:
bool isMan = false;
bool isWoman = false;
Padding(
padding: EdgeInsets.only(right: 10),
child: Text(
"Man:",
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
Theme(
data: ThemeData(unselectedWidgetColor: Colors.white),
child: Checkbox(
value: isMan,
checkColor: Color(0xfff44336),
activeColor: Colors.white,
onChanged: (value) {
setState(
() {
isMan = value!;
},
);
},
),
),
Text(
"Woman:",
style: TextStyle(color: Colors.white, fontSize: 20),
),
Theme(
data: ThemeData(unselectedWidgetColor: Colors.white),
child: Checkbox(
value: isWoman,
checkColor: Color(0xfff44336),
activeColor: Colors.white,
onChanged: (value) {
setState(
() {
isWoman = value!;
},
);
},
),
),
Here is the solution.
bool isMan = false;
bool isWoman = false;
Center(
child: Row(
children: [
Padding(
padding: EdgeInsets.only(right: 10),
child: Text(
"Man:",
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
Theme(
data: ThemeData(unselectedWidgetColor: Colors.white),
child: Checkbox(
value: isMan,
checkColor: Color(0xfff44336),
activeColor: Colors.white,
onChanged: (value) {
setState(
() {
isMan = value!;
isWoman = false;
},
);
},
),
),
Text(
"Woman:",
style: TextStyle(color: Colors.white, fontSize: 20),
),
Theme(
data: ThemeData(unselectedWidgetColor: Colors.white),
child: Checkbox(
value: isWoman,
checkColor: Color(0xfff44336),
activeColor: Colors.white,
onChanged: (value) {
setState(
() {
isWoman = value!;
isMan = false;
},
);
},
),
),
],
),
)
When checkbox is un/checked - change other checkbox value
bool isMan = false;
bool isWoman = false;
#override
Widget build(BuildContext context) {
return Row(children: [
Text("Man:"),
Checkbox(
value: isMan,
onChanged: (value) {
setState(() {
isMan = value!;
isWoman = !value; # or set it to false
});
}),
Text("Woman:"),
Checkbox(
value: isWoman,
onChanged: (value) {
setState(() {
isWoman = value!;
isMan = !value; # or set it to false
});
})
]);
}
I'm trying to update the card data I brought from firestore
when I use onTap in Inkwell I want to change data in this card.
this is my search service. I am using this for bring data from firestore
how can I make update function on this situation. thanks for help
class SearchService {
List<Future<QuerySnapshot>> searchByName() {
return [
Firestore.instance
.collection('dis')
.where('no')
.orderBy('date', descending: true )
.getDocuments(),
];
}
}
this is my Card code
Widget buildResultCard(BuildContext context , data) {
return Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
elevation: 5,
child: ExpansionCard(
title: Column(
children: [
Row(
children: [
Padding(
padding: EdgeInsets.fromLTRB(5, 0, 5, 1),
child: Text(data['isim'],
style: GoogleFonts.montserrat(color: Colors.blueGrey[700], fontSize: 20 , textStyle: TextStyle(fontWeight: FontWeight.w400)),
textAlign: TextAlign.center,
),
),
InkWell(
child: Icon(
Icons.update,
color: Colors.white54,
),
onTap: (){//I want to set update function here//
},
)
],
),
);
}
and this is my adddata function
Future<void> addData(carData) async {
if (isLoggedIn()) {
Firestore.instance.collection('dis').add(carData).catchError((e) {
print(e);
});
} else {
print('You need to be logged in');
}
}
a little bit long but this is my addmethod
crudMedthods crudObj = new crudMedthods();
Future<bool> addDialog(BuildContext context) async {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
final _width = MediaQuery.of(context).size.width;
return AlertDialog(
title: Text('Temsilci Verisi Ekleyin.', style: GoogleFonts.montserrat(color: Colors.black54,
fontSize: 22 , textStyle: TextStyle(fontWeight: FontWeight.w300)),
textAlign: TextAlign.center,),
content: SingleChildScrollView(
child: Container(
width: _width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: [
TextField(
onTap: (){
showDatePicker(context: context,
initialDate: _dateTime == null ? DateTime.now() : _dateTime,
firstDate: DateTime(2000),
lastDate: DateTime(2030)).then((date) {
setState(() {
_dateTime = date;
});
});
},
decoration: InputDecoration(hintText: _dateTime == null ? 'Uygulama Sıralama
Takvimi Giriniz' : _dateTime.toString()),
onChanged: (value) {
this._dateTime = value as DateTime;
},
),
],
),
SizedBox(height: 5.0),
TextField(
decoration: InputDecoration(hintText: 'Temsilci'),
onChanged: (value) {
this.temsilci = value;
},
),
SizedBox(height: 5.0),
TextField(
decoration: InputDecoration(hintText: 'Sıra No'),
onChanged: (value) {
this.sirano = value;
},
),
SizedBox(height: 5.0),
TextField(
decoration: InputDecoration(hintText: 'Tarih'),
onChanged: (value) {
this.tarih = value;
},
),
SizedBox(height: 5.0),
TextField(
decoration: InputDecoration(hintText: 'Veri Kaynağı'),
onChanged: (value) {
this.verik = value;
},
),
],
),
),
),
actions: <Widget>[
FlatButton(
child: Text('Verileri Sisteme Ekleyin'),
textColor: Colors.blue,
onPressed: () {
Navigator.of(context).pop();
crudObj.addData({
'date': this._dateTime,
'no': this.no,
'temsilci': this.temsilci,
'sıra no': this.sirano,
'tarih': this.tarih,
'veri kaynağı': this.verik,
}).then((result) {
dialogTrigger(context);
}).catchError((e) {
print(e);
});
},
)
],
);
});
}
I cannot validate Steps individually. I can validate fields in a Stepper, problem is that I want to validate fields before going to the next step.
Creating multiple forms is not a good option. I tried that and it is not practical. Is there any way to either:
Detect the current step and validate fields only inside that step
A simple way to validate step by step, not on submit
Use List<GlobalKey<FormState>> to control each step's validation
When user click continue do formKeys[currStep].currentState.validate()
You can copy paste run full code below
code snippet
List<GlobalKey<FormState>> formKeys = [GlobalKey<FormState>(), GlobalKey<FormState>(), GlobalKey<FormState>(), GlobalKey<FormState>()];
...
return Container(
child: Form(
key: _formKey,
child: ListView(children: <Widget>[
Stepper(
steps: steps,
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if(formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
});
},
...
List<Step> steps = [
Step(
title: const Text('Name'),
//subtitle: const Text('Enter your name'),
isActive: true,
//state: StepState.error,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: Column(
children: <Widget>[
TextFormField(
focusNode: _focusNode,
keyboardType: TextInputType.text,
autocorrect: false,
onSaved: (String value) {
data.name = value;
},
maxLines: 1,
//initialValue: 'Aseem Wangoo',
validator: (value) {
if (value.isEmpty || value.length < 1) {
return 'Please enter name';
}
},
decoration: InputDecoration(
labelText: 'Enter your name',
hintText: 'Enter a name',
//filled: true,
icon: const Icon(Icons.person),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp( MyApp());
}
List<GlobalKey<FormState>> formKeys = [GlobalKey<FormState>(), GlobalKey<FormState>(), GlobalKey<FormState>(), GlobalKey<FormState>()];
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyAppScreenMode();
}
}
class MyData {
String name = '';
String phone = '';
String email = '';
String age = '';
}
class MyAppScreenMode extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.lightGreen,
),
home: Scaffold(
appBar: AppBar(
title: Text('Steppers'),
),
body: StepperBody(),
));
}
}
class StepperBody extends StatefulWidget {
#override
_StepperBodyState createState() => _StepperBodyState();
}
class _StepperBodyState extends State<StepperBody> {
int currStep = 0;
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
static MyData data = MyData();
#override
void initState() {
super.initState();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
#override
void dispose() {
_focusNode.dispose();
super.dispose();
}
List<Step> steps = [
Step(
title: const Text('Name'),
//subtitle: const Text('Enter your name'),
isActive: true,
//state: StepState.error,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: Column(
children: <Widget>[
TextFormField(
focusNode: _focusNode,
keyboardType: TextInputType.text,
autocorrect: false,
onSaved: (String value) {
data.name = value;
},
maxLines: 1,
//initialValue: 'Aseem Wangoo',
validator: (value) {
if (value.isEmpty || value.length < 1) {
return 'Please enter name';
}
},
decoration: InputDecoration(
labelText: 'Enter your name',
hintText: 'Enter a name',
//filled: true,
icon: const Icon(Icons.person),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
Step(
title: const Text('Phone'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[1],
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.phone,
autocorrect: false,
validator: (value) {
if (value.isEmpty || value.length < 10) {
return 'Please enter valid number';
}
},
onSaved: (String value) {
data.phone = value;
},
maxLines: 1,
decoration: InputDecoration(
labelText: 'Enter your number',
hintText: 'Enter a number',
icon: const Icon(Icons.phone),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
Step(
title: const Text('Email'),
// subtitle: const Text('Subtitle'),
isActive: true,
state: StepState.indexed,
// state: StepState.disabled,
content: Form(
key: formKeys[2],
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.emailAddress,
autocorrect: false,
validator: (value) {
if (value.isEmpty || !value.contains('#')) {
return 'Please enter valid email';
}
},
onSaved: (String value) {
data.email = value;
},
maxLines: 1,
decoration: InputDecoration(
labelText: 'Enter your email',
hintText: 'Enter a email address',
icon: const Icon(Icons.email),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
Step(
title: const Text('Age'),
// subtitle: const Text('Subtitle'),
isActive: true,
state: StepState.indexed,
content: Form(
key: formKeys[3],
child: Column(
children: <Widget>[
TextFormField(
keyboardType: TextInputType.number,
autocorrect: false,
validator: (value) {
if (value.isEmpty || value.length > 2) {
return 'Please enter valid age';
}
},
maxLines: 1,
onSaved: (String value) {
data.age = value;
},
decoration: InputDecoration(
labelText: 'Enter your age',
hintText: 'Enter age',
icon: const Icon(Icons.explicit),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid)),
),
],
),
)),
// Step(
// title: const Text('Fifth Step'),
// subtitle: const Text('Subtitle'),
// isActive: true,
// state: StepState.complete,
// content: const Text('Enjoy Step Fifth'))
];
#override
Widget build(BuildContext context) {
void showSnackBarMessage(String message,
[MaterialColor color = Colors.red]) {
Scaffold
.of(context)
.showSnackBar( SnackBar(content: Text(message)));
}
void _submitDetails() {
final FormState formState = _formKey.currentState;
if (!formState.validate()) {
showSnackBarMessage('Please enter correct data');
} else {
formState.save();
print("Name: ${data.name}");
print("Phone: ${data.phone}");
print("Email: ${data.email}");
print("Age: ${data.age}");
showDialog(
context: context,
child: AlertDialog(
title: Text("Details"),
//content: Text("Hello World"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text("Name : " + data.name),
Text("Phone : " + data.phone),
Text("Email : " + data.email),
Text("Age : " + data.age),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
));
}
}
return Container(
child: ListView(children: <Widget>[
Stepper(
steps: steps,
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if(formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
// else {
// Scaffold
// .of(context)
// .showSnackBar( SnackBar(content: Text('$currStep')));
// if (currStep == 1) {
// print('First Step');
// print('object' + FocusScope.of(context).toStringDeep());
// }
// }
});
},
onStepCancel: () {
setState(() {
if (currStep > 0) {
currStep = currStep - 1;
} else {
currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
RaisedButton(
child: Text(
'Save details',
style: TextStyle(color: Colors.white),
),
onPressed: _submitDetails,
color: Colors.blue,
),
]));
}
}