I am calling form below for add and edit operations.When clicked on edit button I have to get details of particular document based on its unique Id, so when clicked on edit I am calling API in initState() but when clicked on add button I am facing an issue like futureDocuments is not initialised, I cannot initialise it to null also, how to resolve this?
I am also getting an error like dId is not initialised while cliked on add document button
please guide me towards both the initializations
class DocumentForm extends StatefulWidget {
bool update;
final String userName;
//final String createdBY;
DocumentForm(this.userName, this.update);
#override
State createState() {
return _DocumentFormState(this.userName, this.update);
}
}
// AddAppointmentState<AddDocument> createState() => _AddDocumentState();
class _DocumentFormState extends State<DocumentForm> {
final String userName;
String playerId = '';
bool update;
//final String createdBY;
_DocumentFormState(this.userName, this.update);
late final String date1;
late String datainput;
final List<String> items1 = ["Open", "Closed", "Cancel", "Submitted"];
String? selectedItem;
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
TextEditingController docIdController = TextEditingController();
TextEditingController docTitleController = TextEditingController();
TextEditingController tokenNoController = TextEditingController();
TextEditingController addressController = TextEditingController();
TextEditingController cityController = TextEditingController();
TextEditingController docStatusController = TextEditingController();
TextEditingController docTypeController = TextEditingController();
TextEditingController partyNameController = TextEditingController();
TextEditingController durationController = TextEditingController();
TextEditingController pinCodeController = TextEditingController();
TextEditingController rentDescController = TextEditingController();
TextEditingController startDateController = TextEditingController();
TextEditingController endDateController = TextEditingController();
late TextEditingController docstatusController = TextEditingController();
late String docType = docTypeController.text;
late final String createdBY;
final List<String> items = [
"Residential",
"Commercial",
];
String? selectedValue;
late Future<Document>? futureDocuments;
#override
void initState() {
this.update == true
? futureDocuments = DocumentController.fetchDocumentsByID(this.dId)
: futureDocuments = null;
// TODO: implement initState
super.initState();
// initPlatformState();
// initPlatformStateApt();
init();
}
#override
void dispose() {
docStatusController.dispose();
docTypeController.dispose();
super.dispose();
}
Future init() async {
// initPlatformState();
}
#override
Future<Document>? _futureDocument;
body: SafeArea(
child: SingleChildScrollView(
child: Container(
// height: MediaQuery.of(context).size.height,
//width: width * 1,
//height: MediaQuery.of(context).size.height,
alignment: Alignment.center,
padding: const EdgeInsets.all(25),
child: (_futureDocument == null)
? buildColumn(update)
: buildFutureBuilder(),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10))),
),
),
),
Form buildColumn(bool update) {
return Form(
key: formKey,
child: FutureBuilder<Document>(
future: futureDocuments,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
createdBY = snapshot.data!.createdBy;
this.dId = snapshot.data!.docId;
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 5,
),
// SizedBox(
// height: MediaQuery.of(context).size.height * 0.06,
// width: MediaQuery.of(context).size.width * 8,
// child:
Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.95,
height: MediaQuery.of(context).size.height * 0.06,
// height: MediaQuery.of(context).size.height * 0.5,
child: TextFormField(
// minLines: 1,
// maxLines: 5,
// textCapitalization: TextCapitalization.words,
// //autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
// LengthLimitingTextInputFormatter(100),
FilteringTextInputFormatter.allow(
RegExp("[ ',-/ a-z A-Z á-ú Á-Ú 0-9]")),
],
controller: this.update == true
? docTitleController = TextEditingController(
text: '${snapshot.data!.docTitle}')
: docTitleController,
style: TextStyle(fontSize: 12),
// keyboardType: TextInputType.multiline,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30),
)),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Document Title',
hintText: 'Document title required'),
// validator: ,
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(
fontSize: 12,
),
// minLines: 1,
// maxLines: 2,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(14)
],
// //autovalidateMode: AutovalidateMode.onUserInteraction,
controller: this.update == true
? tokenNoController = TextEditingController(
text: '${snapshot.data!.tokenNo}')
: tokenNoController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
counterText: "",
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(30)),
),
focusColor: Color.fromARGB(255, 3, 87,
156), //Color.fromARGB(255, 253, 153, 33),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Token No',
hintText: 'Token no required'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter token No';
} else if (value.length < 14) {
return 'Please enter 14 digits number';
}
return null;
},
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.01,
),
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(fontSize: 12),
// minLines: 1,
// maxLines: 2,
//autovalidateMode: AutovalidateMode.onUserInteraction,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(2)
],
controller: this.update == true
? durationController = TextEditingController(
text: '${snapshot.data!.duration}')
: durationController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(30))),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Duration(M)',
hintText: 'Duration required'),
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')],
),
),
),
),
],
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.06,
width: MediaQuery.of(context).size.width * 0.4,
child: TextFormField(
style: TextStyle(fontSize: 12),
// //autovalidateMode: AutovalidateMode.onUserInteraction,
//FilteringTextInputFormatter.allow(RegExp("[- 0-9]")),
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp("[- 0-9]")),
LengthLimitingTextInputFormatter(10)
],
controller: this.update == true
? startDateController = TextEditingController(
text: '${snapshot.data!.startDate}')
: startDateController,
keyboardType: TextInputType.datetime,
decoration: const InputDecoration(
errorStyle: const TextStyle(fontSize: 0.05),
prefixIcon: Icon(Icons.calendar_month),
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(30))),
hintStyle: TextStyle(fontSize: 12),
labelStyle: TextStyle(
fontSize: 12,
),
labelText: 'Start Date',
hintText: 'yyyy-MM-dd',
),
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(
1991), //DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2101),
// onConfirm:widget.onChanged,
).then((pickedDate) {
if (pickedDate != null) {
// print(
// pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd')
.format(pickedDate);
print(formattedDate);
setState(() {
startDateController.text = formattedDate;
//set output date to TextField value.
});
print(startDateController.text);
} else {
print("Date is not selected");
}
});
final int dur =
int.parse(durationController.text);
var stDate =
DateTime.parse(startDateController.text);
var jiffy = Jiffy(stDate).add(
months: dur,
days: -1,
// days: 1095,
);
DateTime d = jiffy.dateTime;
String s = jiffy.format('yyyy-MM-dd');
setState(() {
endDateController.text = s.toString();
});
},
validator: MultiValidator(
[RequiredValidator(errorText: 'Required*')]),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
height: 30,
width: 150,
child: ElevatedButton(
onPressed: () {
// ******Add new document **********///////
formKey.currentState?.validate();
final isValidForm =
formKey.currentState!.validate();
if (isValidForm && (update == false)) {
final String docTitle =
docTitleController.text;
final int tokenNo =
int.parse(tokenNoController.text)
.toInt();
//final String tokenNo = tokenNoController.text;
final String partyName =
partyNameController.text;
// addStatus(selectedItem!);
final String docType =
selectedValue.toString();
final String docStatus =
selectedItem.toString();
final String address =
addressController.text;
final String city = cityController.text;
final String rentDesc =
rentDescController.text;
final String pinCode =
pinCodeController.text;
final String duration =
durationController.text;
final String startDate =
startDateController.text;
final String endDate =
endDateController.text;
final String createdBy = this.userName;
print('Username :${createdBy}');
final String updatedBy = '';
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentPage(
this.userName,
)));
setState(() {
_futureDocument = createDocument(
// docId,
docTitle,
tokenNo,
partyName,
docType,
address,
city,
pinCode,
duration,
rentDesc,
docStatus,
startDate,
endDate,
createdBy,
updatedBy,
// createdAt,
);
});
// }
//}
}
///*****************/
//****Edit document ******/
else if (isValidForm && update == true) {
final int docid = snapshot.data!.docId;
final String docTitle =
docTitleController.text;
final int tokenNo =
int.parse(tokenNoController.text)
.toInt();
final String partyName =
partyNameController.text;
final String docType =
docTypeController.text;
final String city = cityController.text;
final String address =
addressController.text;
final String pinCode =
pinCodeController.text;
final String duration =
durationController.text;
final String rentDesc =
rentDescController.text;
final String docStatus =
docstatusController.text;
final String startDate =
startDateController.text;
final String endDate =
endDateController.text;
final String createdBy = this.createdBY;
final String updatedBy = this.userName;
print(
'the user name from doc edit page ${this.userName}');
setState(() {
futureDocuments = updateDocument(
docid,
docTitle,
tokenNo,
partyName,
docType,
address,
city,
pinCode,
duration,
rentDesc,
docStatus,
startDate,
endDate,
createdBy,
updatedBy);
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentsDetails(
docid,
this.userName,
)));
});
}
;
},
child: const Text("Save"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Color.fromARGB(255, 253, 153, 33),
//Color.fromARGB(255, 253, 153, 33)
),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(18.0),
//side: BorderSide(color: Colors.red)
),
)))),
],
),
],
);
}
}
return Center(child: const CircularProgressIndicator());
}),
);
//])
//);
}
FutureBuilder<Document> buildFutureBuilder() {
return FutureBuilder<Document>(
future: _futureDocument,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.docTitle);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
You can remove late since it's already nullable. You have to also update the state after assigning it to futureDocuments.
Change late to nullable values using ? operator. i.e
Change from
late final String date1;
late String datainput;
to
final String? date1;
String? datainput;
Now you can assign null to date1 and datainput!
Related
I have four textfields, a title field, a details field, a date field, and a time field. Both the date and time fields are wrapped within a gesture detector, and onTap calls a pickDateAndTime method. The problem is that when I click on the date field and try to manually change the time through the input rather than the dial way, the focus goes to the title field and when I am still on the time picker and type something in the time picker, the title field gets changed with the new input. The weird part is that this error just appeared out of nowhere, and there are no errors reported in the console.
class TodoScreen extends StatefulWidget {
final int? todoIndex;
final int? arrayIndex;
const TodoScreen({Key? key, this.todoIndex, this.arrayIndex})
: super(key: key);
#override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
final ArrayController arrayController = Get.find();
final AuthController authController = Get.find();
final String uid = Get.find<AuthController>().user!.uid;
late TextEditingController _dateController;
late TextEditingController _timeController;
late TextEditingController titleEditingController;
late TextEditingController detailEditingController;
late String _setTime, _setDate;
late String _hour, _minute, _time;
late String dateTime;
late bool done;
#override
void initState() {
super.initState();
String title = '';
String detail = '';
String date = '';
String? time = '';
if (widget.todoIndex != null) {
title = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].title ??
'';
detail = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].details ??
'';
date = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].date!;
time = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].time;
}
_dateController = TextEditingController(text: date);
_timeController = TextEditingController(text: time);
titleEditingController = TextEditingController(text: title);
detailEditingController = TextEditingController(text: detail);
done = (widget.todoIndex == null)
? false
: arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].done!;
}
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(
hour: (TimeOfDay.now().minute > 55)
? TimeOfDay.now().hour + 1
: TimeOfDay.now().hour,
minute: (TimeOfDay.now().minute > 55) ? 0 : TimeOfDay.now().minute + 5);
Future<DateTime?> _selectDate() => showDatePicker(
builder: (context, child) {
return datePickerTheme(child);
},
initialEntryMode: DatePickerEntryMode.calendarOnly,
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(DateTime.now().year + 5));
Future<TimeOfDay?> _selectTime() => showTimePicker(
builder: (context, child) {
return timePickerTheme(child);
},
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.input);
Future _pickDateTime() async {
DateTime? date = await _selectDate();
if (date == null) return;
if (date != null) {
selectedDate = date;
_dateController.text = DateFormat("MM/dd/yyyy").format(selectedDate);
}
TimeOfDay? time = await _selectTime();
if (time == null) {
_timeController.text = formatDate(
DateTime(
DateTime.now().year,
DateTime.now().day,
DateTime.now().month,
DateTime.now().hour,
DateTime.now().minute + 5),
[hh, ':', nn, " ", am]).toString();
}
if (time != null) {
selectedTime = time;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = '$_hour : $_minute';
_timeController.text = _time;
_timeController.text = formatDate(
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute),
[hh, ':', nn, " ", am]).toString();
}
}
#override
Widget build(BuildContext context) {
bool visible =
(_dateController.text.isEmpty && _timeController.text.isEmpty)
? false
: true;
final formKey = GlobalKey<FormState>();
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text((widget.todoIndex == null) ? 'New Task' : 'Edit Task',
style: menuTextStyle),
leadingWidth: (MediaQuery.of(context).size.width < 768) ? 90.0 : 100.0,
leading: Center(
child: Padding(
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.only(left: 0)
: const EdgeInsets.only(left: 21.0),
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () {
Get.back();
},
child: Text(
"Cancel",
style: paragraphPrimary,
),
),
),
),
centerTitle: true,
actions: [
Center(
child: Padding(
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.only(left: 0)
: const EdgeInsets.only(right: 21.0),
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () async {
},
child: Text((widget.todoIndex == null) ? 'Add' : 'Update',
style: paragraphPrimary),
),
),
)
],
),
body: SafeArea(
child: Container(
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0)
: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 15.0),
child: Column(
children: [
Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
validator: Validator.titleValidator,
controller: titleEditingController,
autofocus: true, // problem here
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
maxLength: 25,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
counterStyle: counterTextStyle,
hintStyle: hintTextStyle,
hintText: "Title",
border: InputBorder.none),
style: todoScreenStyle),
primaryDivider,
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
counterStyle: counterTextStyle,
hintStyle: hintTextStyle,
hintText: "Notes",
border: InputBorder.none),
style: todoScreenDetailsStyle),
],
),
),
Visibility(
visible: (widget.todoIndex != null) ? true : false,
child: GestureDetector(
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Completed",
style: todoScreenStyle,
),
Transform.scale(
scale: 1.3,
child: Theme(
data: ThemeData(
unselectedWidgetColor: const Color.fromARGB(
255, 187, 187, 187)),
child: Checkbox(
shape: const CircleBorder(),
checkColor: Colors.white,
activeColor: primaryColor,
value: done,
side: Theme.of(context).checkboxTheme.side,
onChanged: (value) {
setState(() {
done = value!;
});
})),
)
],
),
),
),
GestureDetector(
onTap: () async {
await _pickDateTime();
setState(() {
visible = true;
});
},
child: Column(
children: [
Row(
children: [
Flexible(
child: TextField(
enabled: false,
controller: _dateController,
onChanged: (String val) {
_setDate = val;
},
decoration: InputDecoration(
hintText: "Date",
hintStyle: hintTextStyle,
border: InputBorder.none),
style: todoScreenStyle,
),
),
visible
? IconButton(
onPressed: () {
_dateController.clear();
_timeController.clear();
setState(() {});
},
icon: const Icon(
Icons.close,
color: Colors.white,
))
: Container()
],
),
primaryDivider,
TextField(
onChanged: (String val) {
_setTime = val;
},
enabled: false,
controller: _timeController,
decoration: InputDecoration(
hintText: "Time",
hintStyle: hintTextStyle,
border: InputBorder.none),
style: todoScreenStyle,
)
],
),
),
],
),
),
),
);
}
}
Should I open an issue on Github, as I had not made any changes to the code for it behave this way and also because there were no errors in the console
Here is the full code on Github
Update
Here is a reproducible example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const TodoScreen(),
);
}
}
class TodoScreen extends StatefulWidget {
const TodoScreen({Key? key}) : super(key: key);
#override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
late TextEditingController _dateController;
late TextEditingController _timeController;
late TextEditingController titleEditingController;
late TextEditingController detailEditingController;
late String _setTime, _setDate;
late String _hour, _minute, _time;
late String dateTime;
#override
void initState() {
super.initState();
String title = '';
String detail = '';
String date = '';
String? time = '';
_dateController = TextEditingController(text: date);
_timeController = TextEditingController(text: time);
titleEditingController = TextEditingController(text: title);
detailEditingController = TextEditingController(text: detail);
}
#override
void dispose() {
super.dispose();
titleEditingController.dispose();
detailEditingController.dispose();
_timeController.dispose();
_dateController.dispose();
}
Theme timePickerTheme(child) => Theme(
data: ThemeData.dark().copyWith(
timePickerTheme: TimePickerThemeData(
backgroundColor: const Color.fromARGB(255, 70, 70, 70),
dayPeriodTextColor: Colors.green,
hourMinuteTextColor: MaterialStateColor.resolveWith((states) =>
states.contains(MaterialState.selected)
? Colors.white
: Colors.white),
dialHandColor: Colors.green,
helpTextStyle: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold, color: Colors.green),
dialTextColor: MaterialStateColor.resolveWith((states) =>
states.contains(MaterialState.selected)
? Colors.white
: Colors.white),
entryModeIconColor: Colors.green,
),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
foregroundColor:
MaterialStateColor.resolveWith((states) => Colors.green)),
),
),
child: child!,
);
Theme datePickerTheme(child) => Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
surface: Colors.green,
secondary: Colors.green,
onPrimary: Colors.white,
onSurface: Colors.white,
primary: Colors.green,
)),
child: child!,
);
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(
hour: (TimeOfDay.now().minute > 55)
? TimeOfDay.now().hour + 1
: TimeOfDay.now().hour,
minute: (TimeOfDay.now().minute > 55) ? 0 : TimeOfDay.now().minute + 5);
Future<DateTime?> _selectDate() => showDatePicker(
builder: (context, child) {
return datePickerTheme(child);
},
initialEntryMode: DatePickerEntryMode.calendarOnly,
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(DateTime.now().year + 5));
Future<TimeOfDay?> _selectTime() => showTimePicker(
builder: (context, child) {
return timePickerTheme(child);
},
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.input);
Future _pickDateTime() async {
DateTime? date = await _selectDate();
if (date == null) return;
if (date != null) {
selectedDate = date;
_dateController.text = selectedDate.toString();
}
TimeOfDay? time = await _selectTime();
if (time != null) {
selectedTime = time;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = '$_hour : $_minute';
_timeController.text = _time;
_timeController.text =
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute)
.toString();
}
}
#override
Widget build(BuildContext context) {
bool visible =
(_dateController.text.isEmpty && _timeController.text.isEmpty)
? false
: true;
final formKey = GlobalKey<FormState>();
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
centerTitle: true,
),
body: SafeArea(
child: Container(
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0)
: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 15.0),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14.0)),
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 15.0),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: titleEditingController,
autofocus: true,
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
maxLength: 25,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
hintText: "Title", border: InputBorder.none),
),
Divider(color: Colors.black),
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
hintText: "Notes", border: InputBorder.none),
),
],
),
)),
GestureDetector(
onTap: () async {
await _pickDateTime();
setState(() {
visible = true;
});
},
child: Container(
margin: const EdgeInsets.only(top: 20.0),
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14.0)),
child: Column(
children: [
Row(
children: [
Flexible(
child: TextField(
enabled: false,
controller: _dateController,
onChanged: (String val) {
_setDate = val;
},
decoration: InputDecoration(
hintText: "Date", border: InputBorder.none),
),
),
visible
? IconButton(
onPressed: () {
_dateController.clear();
_timeController.clear();
setState(() {});
},
icon: const Icon(
Icons.close,
color: Colors.white,
))
: Container()
],
),
Divider(
color: Colors.blue,
),
TextField(
onChanged: (String val) {
_setTime = val;
},
enabled: false,
controller: _timeController,
decoration: InputDecoration(
hintText: "Enter", border: InputBorder.none),
)
],
)),
),
],
),
),
),
);
}
}
In your main.dart file, you should return something like this:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
// This allows closing keyboard when tapping outside of a text field
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus &&
currentFocus.focusedChild != null) {
FocusManager.instance.primaryFocus!.unfocus();
}
},
child: // your app's entry point,
);
}
}
Add a focusNode in your textField:
FocusNode focusNode = FocusNode();
TextField(
focusNode: focusNode,
);
And then in the gesture detector, add that following code to unselect the textfield input:
FocusScope.of(context).requestFocus(FocusNode());
simply wrap your Scaffold widget GestureDetector and add FocusScope.of(context).requestFocus(FocusNode()); it will automatically unfocused text field when you click anywhere on your screen
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Scaffold()
)
You can use below code to remove focus in gesture detector event
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
currentFocus.unfocus();
}
Im trying to make changes in the existing code where in Firstpage it take the name of the trip and StartDate and Endate and other details. When the user click on upload image and comeback to main page I'm able to save the other field data in void savedata() but I'm stuck with how to store the data of startdate and enddate what the user has chosen before he going to second page. enter image description here - I have attached the screenshot how it looks when he choose the date and after coming back to firstpage from secondpage it shows like second picture. enter image description here my requirement here is how other field are storing the date I want startdate and enddate also store.
class _MyHomePageState extends State<DataInfoPage> {
_DataInfoPageState createState() => _DataInfoPageState();
String date = "";
final FirebaseAuth _auth = FirebaseAuth.instance;
User? user;
var name = '';
#override
void initState() {
super.initState();
initUser();
savedata();
}
initUser() async {
user = (_auth.currentUser!);
name = user!.displayName!;
setState(() {});
}
void savedata() {
final absavedata = context.read<AddTripBloc>();
if (absavedata.tripname != null) {
tripname.text = absavedata.tripname!;
//_selectedDateRange!.start = absavedata.sdate;
//_selectedDateRange!.end;
noofdays.text = absavedata.noofdays!;
noofnights.text = absavedata.noofnights!;
slotavail.text = absavedata.slotavail!;
priceperpers.text = absavedata.priceperpers!;
}
}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
// DateTime selectedDate = DateTime.now();
//DateTime startDate = DateTime();
TextEditingController tripname = new TextEditingController();
TextEditingController noofdays = new TextEditingController();
TextEditingController noofnights = new TextEditingController();
TextEditingController slotavail = new TextEditingController();
TextEditingController priceperpers = new TextEditingController();
DateTimeRange? startdate;
DateTimeRange? enddate;
DateTimeRange? _selectedDateRange;
String _displayText(String begin, DateTime? date) {
if (date != null) {
return '$begin Date: ${date.toString().split(' ')[0]}';
} else {
return 'Press the button to show the picker';
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Text(
"Please enter trip details ",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
color: Colors.black),
),
SizedBox(
height: 20,
),
Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
customfields(
hintValue: ' Enter Trip Name',
labeltxt: 'Trip Name *',
keyboardtype: TextInputType.text,
text: tripname),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: _show,
child: const Icon(Icons.date_range_rounded),
shape: BeveledRectangleBorder(
borderRadius: BorderRadius.circular(5))),
Column(
children: [
Text(
_displayText(
'Start', _selectedDateRange?.start),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Colors.black),
),
SizedBox(
height: 20,
),
Text(
_displayText(
'End', _selectedDateRange?.end),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Colors.black))
],
),
SizedBox(
height: 20,
),
],
),
SizedBox(
height: 20,
),
customfields(
hintValue: ' No.of Days *',
labeltxt: 'No.of Days *',
keyboardtype: TextInputType.number,
text: noofdays),
SizedBox(
height: 20,
),
customfields(
hintValue: 'No.of Nights*',
labeltxt: 'No.of Nights*',
keyboardtype: TextInputType.number,
text: noofnights),
SizedBox(
height: 20,
),
customfields(
hintValue: 'Slots Available: *',
labeltxt: 'Slots Available: *',
keyboardtype: TextInputType.number,
text: slotavail,
),
SizedBox(
height: 20,
),
TextFormField(
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.bold),
decoration: InputDecoration(
hintText: 'Price Per Person: *',
labelText: 'Price Per Person: *',
suffixIcon: Icon(
Icons.currency_rupee,
color: Colors.black,
size: 15,
),
),
controller: priceperpers,
keyboardType: TextInputType.number,
validator: (value) {
if (value!.isEmpty) {
return "This Field Can't be empty.";
}
return null;
},
),
// customfields(
// hintValue: 'Price Per Person: *',
// labeltxt: 'Price Per Person: *',
// keyboardtype: TextInputType.number,
// text: priceperpers,
// ),
//Text("Slots Available"),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () async {
final ab = context.read<AddTripBloc>();
ab.setpageonedata(
tripname.text,
_selectedDateRange!.start,
_selectedDateRange!.end,
noofdays.text,
noofnights.text,
slotavail.text,
priceperpers.text);
await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CameraWidget()));
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => CameraWidget()));
},
child: const Text("Upload Images of Trip *"),
),
SizedBox(
height: 35,
),
ElevatedButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
final ab = context.read<AddTripBloc>();
ab.setpageonedata(
tripname.text,
_selectedDateRange!.start,
_selectedDateRange!.end,
noofdays.text,
noofnights.text,
slotavail.text,
priceperpers.text);
//ab.savetripdata(user!);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PageTwo()));
}
setState(() {
_formKey.currentState?.save();
});
},
child: const Text("Save and Continue"),
)
],
)),
],
),
),
));
}
void _show() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
currentDate: DateTime.now(),
saveText: 'Done.',
);
if (result != null) {
// Rebuild the UI
String startdate = result.start.toString();
String enddate = result.end.toString();
// print(startdate);
//print(enddate);
//print(result.start.toString());
//print(result.end.toString());
setState(() {
startdate = result.start.toString();
enddate = result.end.toString();
_selectedDateRange = result;
});
}
}
}
I'm stuck with one issue where once I click on the upload image button it will take me to the next page wherein upload image class I will choose the images from the camera or Gallery and I will click on done. In the done button I have written navigation. pop(context) to the first page but when I come back all the text field data is cleared whatever I have entered and again I need to enter it back which is quite frustrating all the time...PLease help me to solve the issue or show the way how to save the data?
import '../blocs/addtrip_bloc.dart';
import '../widgets/customtextformfield.dart';
import 'CameraWidgetState.dart';
class DataInfoPage extends StatefulWidget {
const DataInfoPage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<DataInfoPage> {
_DataInfoPageState createState() => _DataInfoPageState();
String date = "";
final FirebaseAuth _auth = FirebaseAuth.instance;
User? user;
var name = '';
#override
void initState() {
super.initState();
initUser();
savedata();
}
initUser() async {
user = (await _auth.currentUser!);
name = user!.displayName!;
setState(() {});
}
void savedata() {
final absavedata = context.read<AddTripBloc>();
}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
DateTime selectedDate = DateTime.now();
TextEditingController tripname = new TextEditingController();
TextEditingController sdate = new TextEditingController();
DateTimeRange? _selectedDateRange;
String _displayText(String begin, DateTime? date) {
if (date != null) {
return '$begin Date: ${date.toString().split(' ')[0]}';
} else {
return 'Press the button to show the picker';
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Text(
"Please enter trip details ",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
color: Colors.black),
),
SizedBox(
height: 20,
),
Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
customfields(
hintValue: ' Enter Trip Name',
labeltxt: 'Trip Name *',
keyboardtype: TextInputType.text,
text: tripname),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: _show,
child: const Icon(Icons.date_range),
shape: BeveledRectangleBorder(
borderRadius: BorderRadius.circular(5))),
Column(
children: [
Text(
_displayText(
'Start', _selectedDateRange?.start),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Colors.black),
),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CameraWidget()));
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => CameraWidget()));
},
child: const Text("Upload Images of Trip *"),
),
SizedBox(
height: 35,
),
],
)),
],
),
),
));
}
void _show() async {
final DateTimeRange? result = await showDateRangePicker(
context: context,
firstDate: DateTime(2022, 1, 1),
lastDate: DateTime(2030, 12, 31),
currentDate: DateTime.now(),
saveText: 'Done.',
);
if (result != null) {
// Rebuild the UI
print(result.start.toString());
setState(() {
_selectedDateRange = result;
});
}
}
}
Custom Flied Code
class customfields extends StatelessWidget {
customfields(
{required this.hintValue,
this.labeltxt = "",
required this.keyboardtype,
this.maxvalue = 1,
required this.text});
String hintValue;
String labeltxt;
int maxvalue;
TextInputType keyboardtype;
TextEditingController text;
bool _validate = false;
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
TextFormField(
controller: text,
cursorColor: Colors.black,
//textAlign: TextAlign.left,
// autocorrect: true,
// textInputAction: TextInputAction.go,
// maxLines: maxvalue,
// autofocus: true,
style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
textAlignVertical: TextAlignVertical.center,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp('[a-z A-Z 0-9 #?!#%^&* ? # ^_ . : ! | "" \'-]')),
],
decoration: InputDecoration(
border: new UnderlineInputBorder(
// borderRadius: new BorderRadius.circular(5.0),
// borderSide: new BorderSide(),
),
hintText: hintValue,
labelText: labeltxt,
errorText: _validate ? 'Value Can\'t Be Empty' : null,
//prefixIcon: Icon(Icons),
//suffixIcon: Icon(Icons.currency_bitcoin)
),
keyboardType: keyboardtype,
validator: (value) {
if (value!.isEmpty) {
return "Value Can't be empty.";
}
return null;
},
),
],
),
);
}
}
I am getting error on red screen right after i run my app. My first screen is login screen. I want to simply register the user and login the user. but when i use the getUsers() or getLogin() I get the above error. I am fed up of this error. Searched everywhere but m not able to find any working solutions. Please can u please write the code which i need to add. Please help me.
UserLogin.dart
import 'dart:ui';
import 'package:customer/models/registerUser.dart';
import 'package:customer/screens/UserRegistration.dart';
import 'package:customer/screens/people_list.dart';
import 'package:customer/services/db_service.dart';
import 'package:customer/utils/form_helper.dart';
import 'package:flutter/material.dart';
import 'ForgotPassword.dart';
class UserLogin extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return UserLoginState();
}
}
class UserLoginState extends State<UserLogin>{
final reguser = RegisterUser();
String name,_password,_email;
var _formKey=GlobalKey<FormState>();
RegisterUser model;
DBService dbService;
var _minimumPadding = 5.0;
TextEditingController usernameController=TextEditingController();
TextEditingController passwordController=TextEditingController();
bool isHiddenPassword=true;
final scaffoldKey = new GlobalKey<ScaffoldState>();
void _showSnackBar(String text) {
scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(text),
));
}
void _togglePasswordView() {
setState(() {
isHiddenPassword = !isHiddenPassword;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Customer Tracking System'),),
body:_fetchData(),
);
}
Widget _fetchData(){
return FutureBuilder<List<RegisterUser>>(
future: dbService.getUsers(),
builder:
(BuildContext context, AsyncSnapshot<List<RegisterUser>> userDetails) {
if (userDetails.hasData) {
return _loginUI(userDetails.data);
}
return CircularProgressIndicator();
},
);
}
Widget _loginUI(List<RegisterUser> userDetails){
TextStyle textStyle = Theme.of(context).textTheme.title;
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
Form(
key: _formKey,
child: Container(
child: Padding(
padding: EdgeInsets.all(_minimumPadding * 2),
child: ListView
(
children: <Widget>[
Text("Login".toUpperCase(),
style: TextStyle(
fontSize: 40.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
SizedBox(height: height * 0.08,),
Divider(),
Padding(
padding: EdgeInsets.only(
top: _minimumPadding * 3,
bottom: _minimumPadding),
child: TextFormField(
controller: usernameController,
style: textStyle,
validator: (String value) {
if (value.isEmpty) {
return 'Please Enter Name';
}
return null;
},
onSaved: (String value) {
_email = value;
},
decoration: InputDecoration(
// filled: true,
//fillColor: Colors.white,
prefixIcon: Icon(Icons.person),
labelText: 'Username',
hintText: 'Username',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0)
)
)
)),
Padding(
padding: EdgeInsets.only(
top: _minimumPadding * 3,
bottom: _minimumPadding),
child: TextFormField(
style: textStyle,
obscureText: isHiddenPassword,
controller: passwordController,
validator: (String value) {
if (value.isEmpty) {
return 'Please Enter Name';
}
return null;
},
onSaved: (String value) {
_password = value;
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.lock),
suffixIcon: InkWell(
onTap: _togglePasswordView,
child: Icon(Icons.visibility)),
labelText: 'Password',
hintText: 'Password',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0)
)
)
)
),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ForgotPassword()));
},
child: Text(
"Forgot Password ?",
style: TextStyle(
fontSize: 18,
color: Colors.purpleAccent,
//fontWeight: FontWeight.bold,
letterSpacing: 1.7),
textAlign: TextAlign.right,
),
),
SizedBox(
height: height * 0.08,
),
GestureDetector(
onTap: () {
_submit();
},
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 26, vertical: 20),
decoration: BoxDecoration(
//gradient: new LinearGradient(
//colors: [Colors.purple, Colors.purpleAccent]),
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
blurRadius: 4,
//color: Colors.purpleAccent,
offset: Offset(2, 2))
]),
child: Text(
"Login".toUpperCase(),
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
letterSpacing: 1.7),
textAlign: TextAlign.center,
),
),
),
SizedBox(
height: height * 0.05,
),
SizedBox(
height: height * 0.05,
),
Row(
children: <Widget>[
Expanded(
child: Text("Not yet registered?",
style: TextStyle(
fontSize: 25.0)
)
),
GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => UserRegistration()));
},
child: Center(
child: Container(
padding:
EdgeInsets.symmetric(
horizontal: 26, vertical: 10),
decoration: BoxDecoration(
//gradient: new LinearGradient(
// colors: [Colors.purple, Colors.purpleAccent]),
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
blurRadius: 4,
//color:,
offset: Offset(2, 2))
]),
child: Text(
"Register".toUpperCase(),
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
letterSpacing: 1.7),
textAlign: TextAlign.center,
),
),
),
)
],
),
],
)),
),
);
}
bool validateAndSave() {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
void _submit(){
final form = _formKey.currentState;
var res;
if (validateAndSave()) {
setState(() {
//getLogin(_email, _password);
res=dbService.getLogin(_email, _password).then((value) {
if(res!=0){
FormHelper.showMessage(
context,
"Login",
"Login Successfull",
"Ok",
() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => People_List(),
),
);
},
);}
else {
FormHelper.showMessage(
context,
"Login",
"Login not Successfull",
"Ok", () {}
);
}
});
});
}
}
}
RegisterUser.dart
import 'model.dart';
class RegisterUser extends Model {
static String table = 'userDetails';
int id;
String firstName;
String lastName;
String mobileNum;
String emailId;
String address;
String userType;
String password;
RegisterUser({
this.id,
this.firstName,
this.lastName,
this.mobileNum,
this.emailId,
this.address,
this.userType,
this.password
});
static RegisterUser fromMap(Map<String, dynamic> map) {
return RegisterUser(
id: map["id"],
firstName: map['firstName'].toString(),
lastName: map['lastName'],
mobileNum: map['mobileNum'],
emailId: map['emailId'],
address: map['address'],
userType: map['userType'],
password: map['password']
);
}
Map<String, dynamic> toMap() {
Map<String, dynamic> map = {
'id': id,
'firstName': firstName,
'lastName': lastName,
'mobileNum': mobileNum,
'emailId': emailId,
'address': address,
'userType':userType,
'password':password
};
if (id != null) {
map['id'] = id;
}
return map;
}
}
db_service.dart
import 'package:customer/models/registerUser.dart';
import 'package:customer/utils/database_helper.dart';
Future<List<RegisterUser>> getUsers() async {
await DB.init();
List<Map<String, dynamic>> userDetails = await DB.query(RegisterUser.table);
return userDetails.map((item) => RegisterUser.fromMap(item)).toList();
}
Future<List<RegisterUser>> getLogin(String email, String password) async {
await DB.init();
List<Map<String, dynamic>> res = await DB.rawQuery("SELECT * FROM userDetails WHERE emailId = '$email' and password = '$password'");
if (res.length > 0) {
return res.map((item) => RegisterUser.fromMap(item)).toList();
//return new User.fromMap(res.first);
}
return null;
}
You need a line with dbService = something before you can do dbService.getUsers() because just saying DbService dbService; initializes it to be null.
It's like a paper with no phone number on it and you are trying to call someone with it. You need to write down a phone number on it.
I finally got the answer to my question.
I had to just instantiate the DBService.
i.e DBService dbService=new DBService();
class UserLoginState extends State<UserLogin>{
final reguser = RegisterUser();
String name,_password,_email;
var _formKey=GlobalKey<FormState>();
RegisterUser model;
DBService dbService=new DBService();
...
im have prorblem with formstate retrun false when validation and it should be true who can solve this problem ?
i'm new in Flutter and i am trying to create sign-in form validation but always get false when i call formKey.currentState.validate(). formKey is global key form state
I am defining the key for my form like so:
class LoginState extends State<LogIn> {
final name = TextEditingController();
// TextEditingController name = new TextEditingController();
final password = TextEditingController();
final email = TextEditingController();
// TextEditingController email = new TextEditingController();
// TextEditingController password = new TextEditingController();
TextEditingController cofipassword = new TextEditingController();
GlobalKey<FormState> formstatesingup = new GlobalKey<FormState>();
GlobalKey<FormState> formstatesingin = new GlobalKey<FormState>();
the function look like :
singin() {
var formdate = formstatesingin.currentState;
if (formdate.validate()) {
// formdate.save();
// var data = {'email': email.text, 'password': password.text};
// var response = await http.post(
// Uri.parse('https://onlinestore1997.000webhostapp.com/login.php'),
// body: data);
// var responsebody = jsonDecode(response.body);
// if (responsebody['status'] == 'success') {
// print(responsebody['username']);
// }
//
print('vaildate');
} else {
print(Text(email.text));
print(formstatesingin.currentState.validate());
print('not vaildate');
}
}
formbox :
Center buildFormBoxSingIn(double mdw) {
return Center(
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutBack,
margin: EdgeInsets.only(top: 20),
height: 250,
width: mdw / 1.2,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [BoxShadow(color: Colors.black, spreadRadius: 1)]),
child: Form(
key: formstatesingin,
child: Container(
margin: EdgeInsets.only(top: 20),
padding: EdgeInsets.all(10),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//start
Text(' Email ',
style: TextStyle(
color: Colors.blue[800],
)),
SizedBox(
height: 10,
),
buildTextFormFieldAll(
"Enter your Email", false, email, vaildglobal),
//end Email
SizedBox(
height: 10,
),
//start
Text(' Passworld ',
style: TextStyle(
color: Colors.blue[800],
)),
SizedBox(
height: 10,
),
buildTextFormFieldAll(
"Enter passworld", true, password, vaildglobal),
//end Email
],
),
),
),
),
),
);
}
text form like this :
TextFormField buildTextFormFieldAll(String myhinttext, bool pass,
TextEditingController myController, myvalid) {
return TextFormField(
validator: myvalid,
controller: myController,
obscureText: pass,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(4),
hintText: myhinttext,
filled: true,
fillColor: Colors.grey[100],
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey[500], style: BorderStyle.solid, width: 1)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.blue[500], style: BorderStyle.solid, width: 1)),
));
}
in function valid donet write return " " in the end validator
validator: (value) {if (value == null || value.isEmpty)
return "Invalid mobile number";
return " " //is not correct
},
//Write Like this
That's how I do it:
onPressed: () {
final isValidForm = _yourFormKey.currentState!.validate();
if (isValidForm) {
//Do something
}
}
And make sure that you are doing the validation correctly:
validator: (String? value) {
if (value == null || value.isEmpty) {
return 'Email Required';
}
return null;
},