I have two TextFormField startdate and enddate that takes date as a input from date picker. i want to restrict that user can not allow to select enddate before selected startdate.Be able to select from after selected startdate.how can i manage that.
Here is my cample code
TextFormField(
controller: startDate,
readOnly: true,
validator: (startDate){
if(startDate==null|| startDate.isEmpty){
return "Please Input Start Date";
}else return null;
},
onTap: () async{
DateTime? startPickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate:DateTime.now(),
lastDate: DateTime(2100)
);
if(startPickedDate!= null){
String formattedDate = DateFormat('dd-MM-yyyy').format(startPickedDate);
setState(() {
startDate.text = formattedDate; //set output date to TextField value.
});
}
},
)
TextFormField(
controller: endDate,
readOnly: true,
validator: (endDate){
if(endDate==null || endDate.isEmpty){
return "Please Input End Date";
}else return null;
},
onTap: () async{
DateTime? endPickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2100),
);
if(endPickedDate!= null){
String formattedDate = DateFormat('dd-MM-yyyy').format(endPickedDate);
setState(() {
endDate.text = formattedDate;
}
);
}
},
),
All you need is a check to see if startDate controller is empty or not. If it is not empty show date picker. Check the following code for implementation:
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late TextEditingController startDate;
late TextEditingController endDate;
#override
void initState() {
startDate = TextEditingController();
endDate = TextEditingController();
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
TextFormField(
controller: startDate,
readOnly: true,
validator: (startDate){
if(startDate==null|| startDate.isEmpty){
return "Please Input Start Date";
}else return null;
},
onTap: () async{
DateTime? startPickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate:DateTime.now(),
lastDate: DateTime(2100)
);
if(startPickedDate!= null){
String formattedDate = DateFormat('dd-MM-yyyy').format(startPickedDate);
setState(() {
startDate.text = formattedDate; //set output date to TextField value.
});
}
},
),
TextFormField(
controller: endDate,
readOnly: true,
validator: (endDate){
if(endDate==null || endDate.isEmpty){
return "Please Input End Date";
}else {
return null;
}
},
onTap: () async{
if (startDate.text.isNotEmpty) {
String dateTime = startDate.text;
DateFormat inputFormat = DateFormat('dd-MM-yyyy');
DateTime input = inputFormat.parse(dateTime);
DateTime? endPickedDate = await showDatePicker(
context: context,
initialDate: input.add(const Duration(days: 1)),
firstDate: input.add(const Duration(days: 1)),
lastDate: DateTime(2100),
);
if(endPickedDate!= null){
String formattedDate = DateFormat('dd-MM-yyyy').format(endPickedDate);
setState(() {
endDate.text = formattedDate;
}
);
}
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('You need to select Start Date')));
}
},
),
],
);
}
}
You can check the text of startDate controller. If it is empty (i.e ''), the date picker will not be triggered.
controller: endDate,
readOnly: true,
validator: (endDate) {
if (endDate == null || endDate.isEmpty) {
return "Please Input End Date";
} else
return null;
},
onTap: () async {
if (startDate.text.isNotEmpty) {
DateTime? endPickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2100),
);
if (endPickedDate != null) {
String formattedDate = DateFormat('dd-MM-yyyy').format(endPickedDate);
setState(() {
endDate.text = formattedDate;
});
}
}
},
),
DateTime? startPickedDate
Define this variable outside the build method. When the start date is selected update this variable. Then in end date add this variable as the first date in date picker
Please update your Text form fields with the below code.
Added Text formfield and the start & end date. I have set 40 days range initially for start and end date. you can update this as per your need.
TextEditingController startDateController = TextEditingController();
TextEditingController endDateController = TextEditingController();
DateTime startDate = DateTime.now().subtract(Duration(days: 40));
DateTime endDate = DateTime.now().add(Duration(days: 40));
Build method column code
Column(children: [
TextFormField(
controller: startDateController,
readOnly: true,
validator: (startDate) {
if (startDate == null || startDate.isEmpty) {
return "Please Input Start Date";
} else
return null;
},
onTap: () async {
DateTime? startPickedDate = await showDatePicker(
context: context,
fieldLabelText: "Start Date",
initialDate: startDate,
firstDate: startDate,
lastDate: endDate);
if (startPickedDate != null) {
String formattedDate =
DateFormat('dd-MM-yyyy').format(startPickedDate);
setState(() {
startDate = startPickedDate;
startDateController.text =
formattedDate; //set output date to TextField value.
});
}
},
),
TextFormField(
controller: endDateController,
readOnly: true,
validator: (endDate) {
if (endDate == null || endDate.isEmpty) {
return "Please Input End Date";
} else
return null;
},
onTap: () async {
DateTime? endPickedDate = await showDatePicker(
context: context,
fieldLabelText: "End Date",
initialDate: startDate,
firstDate: startDate,
lastDate: endDate,
);
if (endPickedDate != null) {
String formattedDate =
DateFormat('dd-MM-yyyy').format(endPickedDate);
setState(() {
endDate = endPickedDate;
endDateController.text = formattedDate;
});
}
},
),
]
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(),
),
This is the code i use to show time picker
var selectedTime;
void initState() {
super.initState();
selectedDate = DateTime.now();
selectedTime = TimeOfDay(hour: 23, minute: 23);
}
_selectTime(BuildContext context) async {
final TimeOfDay? picked = await showTimePicker(
context: context,
initialTime: selectedTime,
);
if(picked != null && picked != selectedTime)
setState(() {
selectedTime = picked;
});
}
This is the code i used to send data to another screen
SizedBox(width: 120,
child: ElevatedButton(
child: Text('Continue'),
onPressed: (){
widget.book.selectedDate = selectedDate;
widget.book.selectedTime= selectedTime;
Navigator.push(context, MaterialPageRoute(builder: (context)=> NewBookFinishView(book: widget.book)),
);
},
),
)
but when i press continue to send the value of date and time i get an error
TimeOfDay' is not a subtype of type 'DateTime? please help.
You try to assign twice your widget.book.selectedDate inside your onPressed (you might have used the wrong variable):
widget.book.selectedDate = selectedDate; // 1st assign with a DateTime
widget.book.selectedDate = selectedTime; // 2nd assign with a TimeOfDay
And even if your selectedDate is a dynamic with the 1st assignation being a DateTime you won't be able to assign the value of selectedTime as it is of type TimeOfDay.
can't get the date picked from my datepicker though i didn't getting error on my code.
Future selectDate() async {
DateTime picked = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime(2016),
lastDate: new DateTime(2222));
if (picked != null) setState(() => picked = datepicked);
else{
print(picked);
}
}
}
You need to pass the context in the datepicker method. Complete working code below:
body: Center(
child: RaisedButton(
child: Text('click'),
onPressed: () {
selectDate(context);
}
)
),
Future selectDate(BuildContext context) async {
DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: new DateTime(2016),
lastDate: new DateTime(2222));
if (picked != null && picked!= selectedDate) {
setState(() => selectedDate = picked);
print(picked);
}
else{
print(picked);
}
}
// 2020-02-21 00:00:00.000
I have two separate buttons, one to select a date and one to select a time. How am I able to select both the date and then time by only having a single button?
For example, one the click of a "Schedule" button, a Datepicker will popup. Once the user selects a date and clicks "OK" in the Datepicker, the Timepicker will be called or popup.
This is the code for my time and date button widgets:
DateTime _date = new DateTime.now();
TimeOfDay _time = new TimeOfDay.now();
Future<Null> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: _date,
firstDate: new DateTime(2019),
lastDate: new DateTime(2021),
);
if(picked != null && picked != _date) {
print('Date selected: ${_date.toString()}');
setState((){
_date = picked;
});
}
}
Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: _time,
);
if(picked != null && picked != _time) {
print('Time selected: ${_time.toString()}');
setState((){
_time = picked;
});
}
}
Widgets:
final buttonRow = new Wrap(children: <Widget>[
new RaisedButton(
child: new Text('Select Date'),
onPressed: (){_selectDate(context);}
),
new RaisedButton(
child: new Text('Select Time'),
onPressed: (){_selectTime(context);}
)
]);
RaisedButton(
child: new Text('Select Date and Time'),
onPressed: (){ _selectDateAndTime(context); }
)
/* ... */
Future<Null> _selectDateAndTime(BuildContext context) async {
await _selectDate(context);
await _selectTime(context);
}