Dialog box is not closing flutter - flutter

Here's my Alert dialog code: I've added Navigator.pop(context); in the tapped method call. But it's not closing.
showLoginDialog(BuildContext context,
{TextEditingController usernameController,
TextEditingController loginController}) {
var textController = new TextEditingController();
var nameTextController = new TextEditingController();
String dateToPost;
Alert(
context: context,
title: "Add Profile",
content: Column(
children: <Widget>[
TextField(
controller: nameTextController,
decoration: InputDecoration(
labelText: 'Name',
),
),
TextField(
controller: textController,
onTap: () async {
DateTime date = DateTime(1900);
//FocusScope.of(context).requestFocus(new FocusNode());
date = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime.now());
var formatter = new DateFormat('dd MMM yyyy');
var formatterToPost = new DateFormat('yyyy-MM-dd');
String formatted = formatter.format(date);
dateToPost = formatterToPost.format(date);
print(formatted);
textController.text = formatted;
},
decoration: InputDecoration(
labelText: 'Birth Date',
),
),
],
),
buttons: [
DialogButton(
onPressed: () {
Navigator.pop(context);
_saveData(textController.text, nameTextController.text,
dateToPost);
},
child: Text(
"Add",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
}
Also, is shows error on second time click: The method 'call' was called on null.
Receiver: null
Tried calling: call()

I've solved this issue using
Navigator.of(context, rootNavigator: true).pop();

You should save the data before you close the application.
And instead of Navigator.pop(context) do Navigator.of(context).pop(true)
onPressed: () {
_saveData(textController.text, nameTextController.text,
dateToPost);
Navigator.of(context).pop(true);
}

Related

How to disable Flutter DatePicker?

I have an issue with DatePicker in my application. Here's a simple TextFormField that I've created in my app which will open up DatePicker whenever the user taps on it.
This widget is a part of a form where I also have specified the GlobalKey and TextController for it. The rightmost calendar icon uses the suffixIcon property of InputDecoration and it changes to a clear icon whenever the user selects a date.
Here's the code for the above widget.
TextFormField(
onTap: () => _selectStartDate(context),
controller: _startDateTextController,
keyboardType: TextInputType.datetime,
readOnly: true,
decoration: InputDecoration(
suffixIcon: showClear ? IconButton(
icon: Icon(Icons.clear),
onPressed: _clearStartDate,
) : Icon(Icons.date_range),
labelText: 'Start Date',
labelStyle: TextStyle(
fontSize: AppDimensions.font26,
color: AppColors.paraColor
),
),
validator: (value){
if(value!.isEmpty) {
return 'Please enter a date';
}
},
),
My goal is to let the user pick on a date, and clear it should they choose to do so.
Here's the code for the _selectStartDate and _clearStartDate functions as well as the necessary controller and key. I'm using the intl package to format the date.
final _formKey = GlobalKey<FormState>();
TextEditingController _startDateTextController = TextEditingController();
DateTime selectedStartDate = DateTime.now();
bool showClear = false;
_selectStartDate(BuildContext context) async {
final DateTime? newStartDate = await showDatePicker(
context: context,
initialDate: selectedStartDate,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
helpText: 'STARTING DATE'
);
if(newStartDate != null && newStartDate != selectedStartDate) {
setState(() {
selectedStartDate = newStartDate;
_startDateTextController.text = DateFormat.yMMMd().format(selectedStartDate);
showClear = true;
});
}
}
_clearStartDate() {
_startDateTextController.clear();
setState(() {
showClear = !showClear;
});
}
When i run the app, the DatePicker pops up and I'm able to select a date. The date is then shown on the TextFormField like the image below.
As you can see the clear icon is displayed. However, when i clicked on it, the DatePicker still popped up. And when i clicked on cancel on the DatePicker window, the TextFormField is cleared as expected.
Here's the complete code.
class BookingForm extends StatefulWidget {
const BookingForm({Key? key}) : super(key: key);
#override
_BookingFormState createState() => _BookingFormState();
}
class _BookingFormState extends State<BookingForm> {
final _formKey = GlobalKey<FormState>();
TextEditingController _startDateTextController = TextEditingController();
DateTime selectedStartDate = DateTime.now();
bool showClear = false;
_selectStartDate(BuildContext context) async {
final DateTime? newStartDate = await showDatePicker(
context: context,
initialDate: selectedStartDate,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
helpText: 'STARTING DATE'
);
if(newStartDate != null && newStartDate != selectedStartDate) {
setState(() {
selectedStartDate = newStartDate;
_startDateTextController.text = DateFormat.yMMMd().format(selectedStartDate);
showClear = true;
});
}
}
_clearStartDate() {
_startDateTextController.clear();
setState(() {
showClear = !showClear;
});
}
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Container(
margin: EdgeInsets.only(left: AppDimensions.width20, right: AppDimensions.width20),
padding: EdgeInsets.all(AppDimensions.height20),
decoration: BoxDecoration(
color: Colors.white70,
borderRadius: BorderRadius.circular(AppDimensions.radius20),
boxShadow: [
BoxShadow(
color: Color(0xFFe8e8e8),
blurRadius: 5.0,
spreadRadius: 1.0,
offset: Offset(2,2)
),
]
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextFormField(
onTap: () => _selectStartDate(context),
controller: _startDateTextController,
keyboardType: TextInputType.datetime,
readOnly: true,
decoration: InputDecoration(
suffixIcon: showClear ? IconButton(
icon: Icon(Icons.clear),
onPressed: _clearStartDate,
) : Icon(Icons.date_range),
labelText: 'Start Date',
labelStyle: TextStyle(
fontSize: AppDimensions.font26,
color: AppColors.paraColor
),
),
validator: (value){
if(value!.isEmpty) {
return 'Please enter a date';
}
},
),
ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.only(
top: AppDimensions.height10,
bottom: AppDimensions.height10,
left: AppDimensions.width45,
right: AppDimensions.width45
),
primary: AppColors.mainColor2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppDimensions.radius20)
)
),
child: SmallText(
text: 'Search',
size: AppDimensions.font26,
color: Colors.white,
),
onPressed: (){
if(_formKey.currentState!.validate()) {
_formKey.currentState!.save();
}
}
),
],
),
),
);
}
}
I'm not sure why this happens. Any help is greatly appreciated. Thank you

ShowTimePicker i need to show the time picker on text field

defultFormField(
controller: timeController,
onSubmit: () {},
onTap: () {
showTimePicker(
useRootNavigator: true,
context: context,
initialTime: TimeOfDay.now(),
).then((value) {
print(value);
});
},
and this is the components
Widget defultFormField({
required Function onTap,
required Function onSubmit,
required TextEditingController controller,
// required TextInputType type,
required String text,
required IconData prefix,
required Function valedate,
}) =>
TextFormField(
controller: controller,
// keyboardType: type,
onTap: () {},
onFieldSubmitted: (s) {},
validator: (s) {
valedate();
},
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: text,
prefixIcon: Icon(prefix),
),
);
Try below code hope its helpful to you. Or you can used this package also.
Declare TimeOfDay class
TimeOfDay _time = TimeOfDay(hour: 00, minute: 00);
Create function for TimePicker
void _selectTime() async {
final TimeOfDay? newTime = await showTimePicker(
context: context,
initialTime: _time,
);
if (newTime != null) {
setState(() {
_time = newTime;
});
}
}
Your Widget
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
decoration: InputDecoration(
hintText: 'Select Time',
border: OutlineInputBorder(),
),
onTap: _selectTime,
),
),
SizedBox(height: 8),
Text(
'Selected time: ${_time.format(context)}',
),
],
),

Late Initialization Error in Flutter because of _startDate

As you can see in the included screenshot, I am getting a LateInitializationError upon running my app. The cause is in the code below, but I can't figure out how to fix it. It certainly has to do with the "late DateTime _startDate;" that I am using, but unsure what the right approach is. Do you have any idea? Thanks in advance for looking into it!
class AddEventPage extends StatefulWidget {
final DateTime? selectedDate;
final AppEvent? event;
const AddEventPage({Key? key, this.selectedDate, this.event})
: super(key: key);
#override
_AddEventPageState createState() => _AddEventPageState();
}
late DateTime _startDate;
late TimeOfDay _startTime;
late DateTime _endDate;
late TimeOfDay _endTime;
class _AddEventPageState extends State<AddEventPage> {
final _formKey = GlobalKey<FormBuilderState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: Icon(
Icons.clear,
color: AppColors.primaryColor,
),
onPressed: () {
Navigator.pop(context);
},
),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () async {
//save
_formKey.currentState!.save();
final data =
Map<String, dynamic>.from(_formKey.currentState!.value);
data["Time Start"] =
(data["Time Start"] as DateTime).millisecondsSinceEpoch;
if (widget.event != null) {
//update
await eventDBS.updateData(widget.event!.id!, data);
} else {
//create
await eventDBS.create({
...data,
"user_id": context.read(userRepoProvider).user!.id,
});
}
Navigator.pop(context);
},
child: Text("Save"),
),
)
],
),
body: ListView(
padding: const EdgeInsets.all(16.0),
children: <Widget>[
//add event form
FormBuilder(
key: _formKey,
child: Column(
children: [
FormBuilderTextField(
name: "title",
initialValue: widget.event?.title,
decoration: InputDecoration(
hintText: "Add Title",
border: InputBorder.none,
contentPadding: const EdgeInsets.only(left: 48.0)),
),
Divider(),
FormBuilderTextField(
name: "description",
initialValue: widget.event?.description,
minLines: 1,
maxLines: 5,
decoration: InputDecoration(
hintText: "Add Details",
border: InputBorder.none,
prefixIcon: Icon(Icons.short_text)),
),
Divider(),
FormBuilderSwitch(
name: "public",
initialValue: widget.event?.public ?? false,
title: Text("Public"),
controlAffinity: ListTileControlAffinity.leading,
decoration: InputDecoration(
border: InputBorder.none,
),
),
Divider(),
Neumorphic(
style: NeumorphicStyle(color: Colors.white),
child: Column(
children: [
GestureDetector(
child: Text(
DateFormat('EEE, MMM dd, yyyy')
.format(_startDate),
textAlign: TextAlign.left),
onTap: () async {
final DateTime? date = await showDatePicker(
context: context,
initialDate: _startDate,
firstDate: DateTime(2000),
lastDate: DateTime(2100),
);
if (date != null && date != _startDate) {
setState(() {
final Duration difference =
_endDate.difference(_startDate);
_startDate = DateTime(
date.year,
date.month,
date.day,
_startTime.hour,
_startTime.minute,
0);
_endDate = _startDate.add(difference);
_endTime = TimeOfDay(
hour: _endDate.hour,
minute: _endDate.minute);
});
}
}),
Container(
child: FormBuilderDateTimePicker(
name: "Time End",
initialValue: widget.selectedDate ??
widget.event?.date ??
DateTime.now(),
initialDate: DateTime.now(),
fieldHintText: "Add Date",
initialDatePickerMode: DatePickerMode.day,
inputType: InputType.both,
format: DateFormat('EEE, dd MMM, yyyy HH:mm'),
decoration: InputDecoration(
border: InputBorder.none,
prefix: Text(' '),
),
),
),
],
),
),
],
),
),
],
),
);
}
}
late to the keyword means that your property will be initialized when you use it for the first time.
You like to initialize like this:
late DateTime _startDate = DateTime.now();
And as well as change the others value respectively
In GestureDetector you are using a Text widget and passing the _startDate as value but you have not assigned any value to it beforehand, this causes this error, try giving it an initial value before using it.
You can use the following code as well :
DateTime? _startDate;
I have exactly problem.
Some objects should not be initialized directly, hence the creation of late.
For example I don't want to initialize a File object at creation, but afterwards I use late but flutter returns an error.strong text.
So run: flutter run --release

Flutter how to display datepicker when textformfield is clicked

new TextFormField(
decoration: new InputDecoration(hintText: 'DOB'),
maxLength: 10,
validator: validateDob,
onSaved: (String val) {
strDob = val;
},
),
Future _selectDate() async {
DateTime picked = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime(2016),
lastDate: new DateTime(2019)
);
if(picked != null) setState(() => _value = picked.toString());
}
I created one textFormField when i click the field i want to display datepicker then i have to select one date from the picker after selecting the date i want to set the selected date in the textFormField.
Update 2020:
As pointed by another answer #Lekr0 this can now be done using onTap() property of TextFormField.
TextFormField(
onTap: (){
// Below line stops keyboard from appearing
FocusScope.of(context).requestFocus(new FocusNode());
// Show Date Picker Here
},
)
Original Answer:
Simple Way of Doing it :
Wrap your TextFormField with IgnorePointer & wrap IgnorePointer with InkWell
InkWell(
onTap: () {
_selectDate(); // Call Function that has showDatePicker()
},
child: IgnorePointer(
child: new TextFormField(
decoration: new InputDecoration(hintText: 'DOB'),
maxLength: 10,
// validator: validateDob,
onSaved: (String val) {},
),
),
),
Also in Your _selectDate() make lastDate: new DateTime(2020)); else you will get error.
TextEditingController dateCtl = TextEditingController();
TextFormField(
controller: dateCtl,
decoration: InputDecoration(
labelText: "Date of birth",
hintText: "Ex. Insert your dob",),
onTap: () async{
DateTime date = DateTime(1900);
FocusScope.of(context).requestFocus(new FocusNode());
date = await showDatePicker(
context: context,
initialDate:DateTime.now(),
firstDate:DateTime(1900),
lastDate: DateTime(2100));
dateCtl.text = date.toIso8601String();},)
You can use OnTap property to achieve this
TextFormField(
onTap: (){
// Below line stops keyboard from appearing
FocusScope.of(context).requestFocus(new FocusNode());
// Show Date Picker Here
},
)
To stop keyboard from appearing, you can set the readOnly property of the TextFormField to true.
TextFormField(
readOnly: true,
...
);
TextEditingController intialdateval = TextEditingController();
Future _selectDate() async {
DateTime picked = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime(2020),
lastDate: new DateTime(2030));
if (picked != null)
setState(
() => { data.registrationdate = picked.toString(),
intialdateval.text = picked.toString()
}
);
}
TextFormField(
// focusNode: _focusNode,
keyboardType: TextInputType.phone,
autocorrect: false,
controller: intialdateval,
onSaved: (value) {
data.registrationdate = value;
},
onTap: () {
_selectDate();
FocusScope.of(context).requestFocus(new FocusNode());
},
maxLines: 1,
//initialValue: 'Aseem Wangoo',
validator: (value) {
if (value.isEmpty || value.length < 1) {
return 'Choose Date';
}
},
decoration: InputDecoration(
labelText: 'Registration Date.',
//filled: true,
icon: const Icon(Icons.calendar_today),
labelStyle:
TextStyle(decorationStyle: TextDecorationStyle.solid),
),
),
I don't know why you want to display DatePicker on click of TextFormField?
BTW you have to set enabled=false property of TextFormField and warp TextFormField to GestureDetector that has onTap property where you can call your DatePicker Method.
final _dateController = useTextEditingController();
TextFormField(
readOnly: true,
controller: _dateController,
decoration: InputDecoration(
labelText: 'Date',
),
onTap: () async {
await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2015),
lastDate: DateTime(2025),
).then((selectedDate) {
if (selectedDate != null) {
_dateController.text =
DateFormat('yyyy-MM-dd').format(selectedDate);
}
});
},
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter date.';
}
return null;
},
)
Try this!
GestureDetector(
onTap: () {
var tm = showCupertinoDatePicker(
firstDate:
defaultDateTime.add(Duration(days: -1)),
lastDate: defaultDateTime.add(Duration(days: 1)),
context: context,
initialDate: newDate);
tm.then((selectedDate) {
if (selectedDate != null) {
setState(() {
newDate = selectedDate;
});
dateController.text =
"${DateTimeUtils.formatDate(newDate)}";
}
});
},
child: AbsorbPointer(
child: TextFormField(
controller: dateController,
autofocus: false,
validator: ((val) {
if (val.trim().isEmpty) {
return “Select Date";
}
return null;
}),
decoration: InputDecoration(
icon: Icon(Icons.today),
suffix: Text("Tap to change",
style: Theme.of(context)
.textTheme
.caption))),
),
),
I'm using all place comman widget

How to show date picker on the onclick of text field instead of keyboard in flutter?

Wish to show date picker when clicking on the TextFormField instead of the keyboard. I have tried using GestureDetector but not working as I expected.
DateTime _date = new DateTime.now();
TimeOfDay _time = new TimeOfDay.now();
Future<Null> _selectedDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: _date,
firstDate: new DateTime(2016),
lastDate: new DateTime(2019));
if (picked != null && picked != _date) {
print("Date selected ${_date.toString()}");
setState(() {
_date = picked;
});
}
}
......
new GestureDetector(
onTap: (){
_selectedTime(context);
},
child:
new TextFormField(
initialValue: convertToDate(_date),
decoration: const InputDecoration(
icon: const Icon(Icons.calendar_today),
hintText: 'Enter your date of event',
labelText: 'Date',
),
keyboardType: null,
),
),
You can wrap your TextField with AbsorbPointer , so your widget tree would look something like this:
GestureDetector(
onTap:()=>showDialog(),
child:AbsorbPointer(
child: MyTextField(),
)
)
You can wrap your TextFormField with an AbsorbPointer (see documentation). It will "absorb" the incoming standard behavior on the child so clicking the TextFormField would do nothing. If you now wrap the AbsorbPointerusing a GestureDetector you can use the onTap() method to call your showDatePicker method.
DateTime selectedDate = DateTime.now();
TextEditingController _date = new TextEditingController();
Future<Null> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1901, 1),
lastDate: DateTime(2100));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
_date.value = TextEditingValue(text: picked.toString());
});
}
// inside Widget build
GestureDetector(
onTap: () => _selectDate(context),
child: AbsorbPointer(
child: TextFormField(
controller: _date,
keyboardType: TextInputType.datetime,
decoration: InputDecoration(
hintText: 'Date of Birth',
prefixIcon: Icon(
Icons.dialpad,
color: _icon,
),
),
),
),
);
The other answers here have many widgets to get the job done. But this can simply done by using TextFormField only. Just set the widget to read only (so that it doesn't take inputs) and then define an onTap. The controller attached to it will take the value from the date picker.
First create a TextFormField widget like this:
TextFormField(
readOnly: true, //this is important
onTap: _selectDate, //the method for opening data picker
controller: _textcontroller, //the controller
),
Now write the _selectDate function:
DateTime dateTime = DateTime.now();
_selectDate() async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: dateTime,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(2101));
if (picked != null) {
dateTime = picked;
//assign the chosen date to the controller
_textController.text = DateFormat.yMd().format(dateTime);
}
}
Personally I think this is the easiest solution.
Try this
GestureDetector(
onTap: () => _selectDate(context),
child: AbsorbPointer(
child: TextField(
controller: textController,
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(10.0),
labelText: widget.hintText,
labelStyle: TextStyle(
color: Colors.black,
fontSize: 16),
// pass the hint text parameter here
hintStyle: TextStyle(
color: Colors.black,
fontSize: 16),
suffixIcon: Icon(
Icons.calendar_today),
),
style: TextStyle(color: Colors.black, fontSize: 18),
),
),
);
Future<Null> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1901, 1),
lastDate: DateTime(2100));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
String convertedDateTime = "${picked.year.toString()}-${picked.month.toString().padLeft(2,'0')}-${picked.day.toString().padLeft(2,'0')}";
// widget.textController.value = TextEditingValue(text: picked.toString());
widget.textController.value = TextEditingValue(text: convertedDateTime);;
});
}
Result
TextField(
controller: TextEditingController()
..text = reservationProvider.date,
decoration: InputDecoration(
suffixIcon: ImageIcon(
AssetImage('images/calendar_today.png'),
color: Colors.black,
)),
readOnly: true,
onTap: () async {
final date = await showDatePicker(
context: context,
firstDate: DateTime(1960),
initialDate: DateTime.now(),
lastDate: DateTime(2100));
if (date != null) {
print(date);
}
},
),