i have this funtion which handles my Date and Time picker widget ...Code bellow...
Future selectDayAndTimeL(BuildContext context) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
setState(() {
selectedDateAndTime = DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
);
// _selectedDate = _selectedDay;
});
// print('...');
}
initially it was inside my add new task class/dart file "Stateful Widget", and everything was working fine but now i want to also use that function on the Home screen when a button is pressed.
Then i checked a StackOverflow question on how to call a function from another dart file which the solution required that i keep the Function on a different dart file then call it from there like this Example
void launchWebView () {
print("1234");
}
when i did i was getting an error which i lookedup and it was because of the "setState" in my function so i needed to put it inside a Stateful widget,
import 'package:flutter/material.dart';
class SelectDateAndTime extends StatefulWidget {
#override
_SelectDateAndTimeState createState() => _SelectDateAndTimeState();
}
class _SelectDateAndTimeState extends State<SelectDateAndTime> {
DateTime? _selectedDate;
// DateTime _selectedDate;
DateTime? selectedDateAndTime;
Future selectDayAndTimeL(BuildContext context) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
setState(() {
selectedDateAndTime = DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
);
// _selectedDate = _selectedDay;
});
// print('...');
}
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
And that was the only difference from my code with the example i followed and i was still getting an error when i tried calling the funtion, and i have checked all the quetions related to clling functions from another dart file / class and none of them had SetState so their solution didn't work for me
This is the error i got when i called just the Function Name
Bellow s the error i got when i tried to call
onPressed: () => selectedDateAndTime!.selectDayAndTimeL(),
what should i do from here?
I'm guessing that you originally had a Statefull widget, that probably looked something like this:
class OriginalWidget extends StatefulWidget {
#override
_OriginalWidgetState createState() => _OriginalWidgetState();
}
class _OriginalWidgetState extends State<OriginalWidget> {
DateTime? _selectedDate;
DateTime? selectedDateAndTime;
Future selectDayAndTimeL(BuildContext context) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
setState(() {
selectedDateAndTime = DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
);
// _selectedDate = _selectedDay;
});
// print('...');
}
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () => selectDayAndTimeL(context));
}
}
Now, what you want to do is to reuse the logic of your selectDayAndTimeL function.
The problem is that both the selectedDateAndTime variable and the setState method are specific to the Statefull widget _OriginalWidgetState.
What you need to do is to modify your selectDayAndTimeL function so that it can take those widget-specific stuff as parameters.
So, in essence what you would do is:
1st create the function as a standalone function, for instance in a new dart file. Make sure to remove the widget-specific stuff from the body and leave them as parameters:
Future selectDayAndTimeL(BuildContext context, void Function(DateTime) onDateAndTimeSelected) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
onDateAndTimeSelected(DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
));
// print('...');
}
2nd, on your new Statefull widgets, you may now call this function, make sure that you send the new onDateAndTimeSelected parameter:
class SecondWidget extends StatefulWidget {
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class _SecondWidgetState extends State<SecondWidget> {
DateTime? selectedDateAndTime;
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () => selectDayAndTimeL(context,
setState((DateTime selectedValue) {
selectedDateAndTime = selectedValue;
} )
));
}
}
And then you could just follow the same logic for any other Statefull widget that needs to call your function.
setState tells a stateful widget to re-render based on the changed data. In your case you are changing selectedDateAndTime and re-building the Widget with updated data.
If you want to update/rebuild a widget from a "remote" function you need to use a callback.
Future selectDayAndTimeL(BuildContext context,Function(DateTime time) onDateTimeSelected) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
// call the callback here with your calculated data
onDateTimeSelected(
DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
),
);
}
Then in the StatefulWidget where you call this function:
selectDayAndTimeL(BuildContext context,(time) {
setState(() {
selectedDateAndTime = time;
});
});
Related
i'va made a TimePicker that will pop up when user taps on textFormField it's working fine but the only problem is that i want to update textFormField value by the one selected from timePicker
I've declared a controller and initilize a selectedTimer
TimeOfDay selectedTime = TimeOfDay(hour: 0, minute: 0);
TextEditingController _timeController = TextEditingController();
And this is the code of TextFormField
TextFormField(
controller: _timeController,
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
_selectTime(context);
},
),
And this is the code for the method _selectTime
_selectTime(BuildContext context) async {
final TimeOfDay? timeOfDay = await showTimePicker(
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.dial,
);
if (timeOfDay != null && timeOfDay != selectedTime) {
setState(() {
selectedTime = timeOfDay;
TextEditingValue(text: timeOfDay.toString());
});
}
}
Do as follows:
_timeController.text=timeOfDay.toString();
selectTime(BuildContext context) async {
final TimeOfDay? timeOfDay = await showTimePicker(
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.dial,
);
if (timeOfDay != null && timeOfDay != selectedTime) {
setState(() {
selectedTime = timeOfDay;
_timeController.text=timeOfDay.toString();
TextEditingValue(text: timeOfDay.toString());
});
}
}
remove this line TextEditingValue(text: timeOfDay.toString());
and replace by this _timeController.text = selectedTime.toString();
This is the screenshot of dialog box where i want to update new date after picked up.
This is what i tried in controller.dart.
class AppointmentController extends GetxController {
String t;
var selectedDate = DateTime.now().obs;
var selectedTime = TimeOfDay.now().obs;
void selectDate() async {
final DateTime pickedDate = await showDatePicker(
context: Get.context,
initialDate: selectedDate.value,
firstDate: DateTime(2018),
lastDate: DateTime(2025),
);
if (pickedDate != null && pickedDate != selectedDate.value) {
selectedDate.value = pickedDate;
}
}
This is what I tried in homepage.dart
Obx(
()=>TextFormField(
onTap:(){
controller.selectDate();
},
initialValue:DateFormat('DD-MM-
yyyy').format(controller.selectedDate.value).toString(),
),
add a TextEditingController to the textformfield and change text with this controller
class AppointmentController extends GetxController {
String t;
var selectedDate = DateTime.now().obs;
var selectedTime = TimeOfDay.now().obs;
TextEditingController textEditingController=TextEditingController();
void selectDate() async {
final DateTime pickedDate = await showDatePicker(
context: Get.context,
initialDate: selectedDate.value,
firstDate: DateTime(2018),
lastDate: DateTime(2025),
);
if (pickedDate != null && pickedDate != selectedDate.value) {
selectedDate.value = pickedDate;
textEditingController.text=DateFormat('DD-MM-
yyyy').format(selectedDate.value).toString();
}
}
Obx(
()=>TextFormField(
controller:controller.textEditingController,
onTap:(){
controller.selectDate();
},
initialValue:DateFormat('DD-MM-
yyyy').format(DateTime.now()).toString(),
),
In this below code to display a date picker in Flutter as I press a button but nothing happens. I tried looking into the docs found noting there are no errors on how I can debug this or get to work.
import "package:flutter/material.dart" ;
import "dart:async";
void main() {
runApp(new MaterialApp(
home: new Baseapp(),
));
}
class Baseapp extends StatefulWidget{
#override
_State createState() => new _State();
}
class _State extends State<Baseapp> {
String _value = '';
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());
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title : new Text("NAME HERE", style :TextStyle(color:Colors.black)),
backgroundColor: Colors.yellow ,
),
body: new Container(
padding : new EdgeInsets.all(20),
child: new Center(
child: new Column(
children:<Widget>[
new Text(_value),
new ElevatedButton(onPressed:_selectDate, child: new Text("Date")),
],
),
),
),
);
}
}
In your showDatePicker function, try implementing a builder, like so:
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1900),
lastDate: lastDate,
//Implement builder here
builder: (context, child) => child,
That should solve the issue.
Future _selectDate() async {
DateTime? picked = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime(2016),
lastDate: new DateTime(2019) //<= you used here past year but you set initial date is today so use here future year such as "lastDate: new DateTime(2019)" other wise intial date set to less than last year
lastDate: new DateTime(2024)
);
you used here last date in past year but you set initial date is today so use here future year such as "lastDate: new DateTime(2019)" other wise intial date set to less than last year
if(picked != null){
setState(() {
int year = picked.year;
int mth = picked.month;
int day = picked.day;
_value = '${day} / ${mth} / ${year}';
});
hey I figured it out XD
this particular code was missing.
thanks
I have this code of time picker, then I want to set the initial Time from a DateTime variable:
Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay pickedS = await showTimePicker(
context: context,
initialTime: createdAt,
builder: (BuildContext context, Widget child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: false),
child: child,
);});
if (pickedS != null && pickedS != selectedTime )
setState(() {
selectedTime = pickedS;
myTweets[actualTweetIndex].createdAt = dateFormat.format(selectedDate.toLocal()) +' ${selectedTime.hour}:${selectedTime.minute}:00 +0000 '+ selectedDate.year.toString();
});
}
The TimeOfDay class have a dedicated constructor for that :
TimeOfDay.fromDateTime(DateTime time)
You can check the documentation here
I want to implement a reminder feature in my application which reminds the user to do a particular task at a selected time. I have implemented a showDatePicker widget to select the date and month but i am unsure on how to display a showTimePicker after a date is selected in the showDatePicker
Could i get a suggestion on how this can be implemented?
code which displays the showDatePicker:
_selectDate() async {
final DateTime picker =await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2010),
lastDate: DateTime(2040)
);
if (picker != null) {
print(picker);
_daysPageController.jumpToDay(picker);
// Navigator.pop(context);
// print(selectedDate);
// await runJump(selectedDate);
// return selectedDate;
}
}
It is very simple, it creates a single function that in sequence calls the methods showDatePicker() and showTimePicker().
Future _selectDayAndTime(BuildContext context) async {
DateTime _selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2018),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget child) => child
);
TimeOfDay _selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if(_selectedDay != null && _selectedTime != null) {
//a little check
}
}