Closed matteoberla closed 2 months ago
@matteoberla
Thank you for the feature suggestion.
As an implementation image, is this correct?
For autocompletion, it would be better to reflect autocompletion in the TextField at the timing when the focus is lost, rather than during input. However, the callback at the time of TextField change detection assumes the value after autocompletion for UX.
We will respond to the package version as we think it is possible.
First of all thanks for the response.
-When a custom TextField is focused, the Picker is displayed from below (focus is maintained). Not mandatory but very cool feature if it's possible.
-When the value of the TextField is changed, the Picker will also change in conjunction with the TextField. this would be perfect
-Return null for dates that are not valid null value of course and also show a red border or something else to the user.
-Allow specifying input format (e.g., dd/mm) yes, i think that yyyy-MM-dd, yyyy/MM/dd, dd/MM/yyyy (the divider could change based on the locale i think, in italy we always use / but idk if it's used worldwide). I've encoutered the case where the user insert 2/3 and shoud become 02/03 automatically. Also, add a customizable hint label as here in italy to indicate dd/mm/yyyy i would use gg/mm/aaaa or maybe let it empty, depends on cases.
Only numbers and delimiters ("/", ":") can be entered I think that the user could also insert "," "-" "." ";" but all of these should be replaced with the correct divider.
For autocompletion, make it after textfield focus lost is perfect so the user sees that the input was accepted.
OK, I understand the overview of the feature. I have a feeling it will be a substantial feature and will take some time. Please wait until we finish implementing the new features!
Yes I understand that it's a big feature and i'll wait for your news.
Thank you very much.
@matteoberla
Although it is not yet complete, I believe it will work for the functions you have in mind, so I would be happy if you could try it out and give us your feedback! As for the seconds, only hours and minutes are supported this time, as Picker itself does not support seconds.
board_datetime_picker:
git:
url: https://github.com/mytooyo/board_datetime_picker
ref: textfield
SizedBox(
width: 160,
child: BoardDateTimeInputField(
pickerType: DateTimePickerType.datetime,
options: const BoardDateTimeOptions(
languages: BoardPickerLanguages.it(),
pickerFormat: PickerFormat.dmy,
),
textStyle: Theme.of(context).textTheme.bodyMedium,
onChanged: (date) {
print('onchanged: $date');
},
),
);
The parameters are identical to the options and types of the existing BoardDateTimeBuilder
and showBoardDateTimePicker
. The input string allowed conforms to the pickerType
.
In addition, the necessary items can be specified in the TextFormField
of the Flutter standard, and the Hint section can also be specified with decoration
.
I am still considering how to generate error messages, but for now I am using the validator
feature of the TextFormField
standard.
Thank you very much.
I've just tested it and here are some considerations. -I would need an "on submit" function so when the user exit from the field I can verify if the inserted date/time is valid and make some others operations on it. In my version i'm currently using a Focus widget wrapped around the textfield and i'm executing a function when the focus is changed
onFocusChange: (hasFocus) {
if (onFocusChanged != null && hasFocus == false) {
onFocusChanged!();
}
},
-autocomplete the year in PickerFormat.dmy, i'm now writing 02/04 and then pressing enter, even if 02/04 is a valid date (as i'm expecting the widget to autocomplete the year to 2024) the date is not returned at the moment. I saw that pressing another "/" the year is autocompleted but i think that for the user won't be that intuitive, if you add the "on submit" you could try to execute the autocompletion at that time.
-I've the italian keyboard so in order to input ":" i've to press Maiusc + "." but at the moment the textfield is adding an "/" and is selecting the whole text. so i'm not getting how to use it manually as the time is not retrieved by the onChanged (using the picker works fine)
-replace "." "," with "/" or ":" based on the picker format. Using the italian keyboard is much faster to input ex. 02.04 than 02/04 or 10.15 than 10:15 (same reason as previous point).
-Error on input, Can you add a parameter in the widget to hide this error string and maintain the red border only?
Seems to be a very good looking starting point, thank you.
@matteoberla
Thanks for trying! We have received feedback and made some corrections. I believe we have fixed the feedback areas that we received with these corrections.
BoardDateTimeInputField(
validators: BoardDateTimeInputFieldValidators(
// If true, a message is displayed at the bottom as in TextFormField
showMessage: false,
// If handling for each error is required, please do it here
// If showMessage is false, the return value can be null
// - Called when the format is invalid.
onIllegalFormat: () => null,
// - Called when outside the specified date and time range.
onOutOfRange: () => null,
// - Called when required checks are needed.
onRequired: () => null,
),
)
I am pushing to the same branch so you can try again!
I'm trying now but i'm facing some issues,
i can't input two digits as the textfield is always selecting all text and overwriting my input. maybe the focus node is not working fine?
I can't find the OnFocusChanged callback and when pressing enter on time text field the time is not retrieved.
Thank you for the explaination about the error handling!
I'm trying now but i'm facing some issues,
i can't input two digits as the textfield is always selecting all text and overwriting my input. maybe the focus node is not working fine?
Thank you for the explaination about the error handling!
I was checking on macOS, so I didn't see the problem, but it seems to occur with Chrome. Please wait a little while while we fix it.
I'm trying now but i'm facing some issues, i can't input two digits as the textfield is always selecting all text and overwriting my input. maybe the focus node is not working fine? Thank you for the explaination about the error handling!
I was checking on macOS, so I didn't see the problem, but it seems to occur with Chrome. Please wait a little while while we fix it.
@matteoberla Fixed cursor position not to be incorrect in Chrome as well. Please check back when you have a moment, as it has been reflected.
Please wait a moment for OnFocusChanged
.
DateTimePickerType.date seems to be fixed and perfecty working. I still can't retrieve the value of the time inserted using the widget with DateTimePickerType.time.
A note about OnFocusChanged: if you can, please pass the date as parameter so i can catch the current value when the user exits from the field and i can also catch null values (not valid dates) and then make some other operations by myself.
I'm also seeing an error in the console when closing the page where the widget is placed, i'm leaving here the exception
The following assertion was thrown while finalizing the widget tree:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
...
packages/board_datetime_picker/src/board_datetime_input_field.dart 387:16 dispose
it seems to be referring to line 387 of the package:
focusNodeDebounce?.cancel();
@matteoberla
For time
, I have prepared an onResult
method, similar to what is supported below.
The onChange
method also returns the selected time on the day.
https://github.com/mytooyo/board_datetime_picker/issues/15
The implementation of OnFocusChanged
is called when the text field gets focus and when the picker is hidden because it is out of focus.
Other errors during screen transitions have also been corrected.
Isn't it possible to expose that onFocusChanged
function or execute a custom function when it is called? I'm going to explain why.
-I need to be able to catch when the user cancel the whole input so i can set that field to null. -I need to know if the date inserted is not valid so i can bring back the initial data value in the textfield otherwise i don't have a callback function for when the user ends the input of the data.
Dispose Error is fixed!
By using onResult i get a new value each time I'm compiling the textform, so i don't get only the final value, but instead all the values between. It would be very useful to have just the final value, for this i was asking for a callback function called when the onFocusChanged
occurs.
Let me know if it makes sense and if it's possible.
Would it be better to say that onFocusChanged is fine as it is now, but provide a way to change the value of a text field from the outside? For example, make the value updatable in textcontroller
Am I correct in understanding that it would be nice to have a way to notify the final value with onCompeted, rather than always receiving a callback? In that case, onFocusChanged and onCompleted would be callback functions with the same meaning, so I think one of them should be unified.
Sorry it was my bad, i didn't see that you already implemented onFocusChange
, it's fine the way you implemented it but i've just tested it and there's something wrong.
My code at the moment has two BoardDateTimeInputField
one with date and one with time, my onFocusChanged is like this
onFocusChange: (hasFocus, finalDate) {
if (!hasFocus) {
print("ora: $finalDate");
}
},
the function is called both in time and date textfields so each time i exit from a field both functions are called, but instead i expect only the field that was focused (but now not anymore) to be called and to retrieve its value.
Hope i explained correcly.
I've found a solution for this but i need your help.
-I've removed the call to onFocusChange
-I've wrapped the TextFormField
in a Focus
Widget and added
onFocusChange: (hasFocus){
checkFormat(textController.text, complete: true);
widget.onFocusChange?.call(hasFocus, selectedDate, textController.text);
},
It works fine but the only case where the selectedDate
is not updated is when i insert an incomplete date (ex. 03 or 03/ ) in fact the validation doesn't return an error and so the selectedDate
is not updated to null.
I've also returned the text so i can check if the user input was a date or if it was an empty string.
Let me know if it could work.
Since it needs to work with the Picker, there are some parts of it that will not work if I just wrap it in a FocusWidget.
Are you saying that the onFocusChange
call in the focusScopeListener
is unnecessary?
Can you tell me again what functionality you want as a feature? (What callbacks would be nice to have)
yes the call in focusScopeListener
is unnecessary as when it is called from one BoardDateTimeInputField
it is called from all the textfields in the code, so for example, if i have 10 textfields all onFocusChange
are fired and it's not what i wanted, instead by using the focus widget only the textfield's onFocusChange
i'm compiling is fired.
But if you tell me that there could be some problems with the picker we need to find another solution.
Basically i want to compile the textfield, once finished (so i exit from that field) i want only the onFocusChange
of that field to be called.
My code at the moment is:
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 160,
child: BoardDateTimeInputField(
pickerType: DateTimePickerType.date,
onFocusChange: (hasFocus, finalDate, stringInput) {
if (!hasFocus) {
print("data: $finalDate, $stringInput");
}
},
options: const BoardDateTimeOptions(
languages: BoardPickerLanguages.it(),
startDayOfWeek: DateTime.monday,
pickerFormat: PickerFormat.dmy,
textColor: darkTextColor,
activeColor: mainColor,
activeTextColor: lightTextColor,
showDateButton: false,
pickerSubTitles: BoardDateTimeItemTitles(
year: "Anno",
month: "Mese",
day: "Giorno",
hour: "Ora",
minute: "Minuto"),
),
onChanged: (date) {},
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 160,
child: BoardDateTimeInputField(
pickerType: DateTimePickerType.time,
delimiter: ":",
onFocusChange: (hasFocus, finalDate, stringInput) {
if (!hasFocus) {
print("ora: $finalDate, $stringInput");
}
},
options: const BoardDateTimeOptions(
languages: BoardPickerLanguages.it(),
startDayOfWeek: DateTime.monday,
pickerFormat: PickerFormat.dmy,
textColor: darkTextColor,
activeColor: mainColor,
activeTextColor: lightTextColor,
showDateButton: false,
pickerSubTitles: BoardDateTimeItemTitles(
year: "Anno",
month: "Mese",
day: "Giorno",
hour: "Ora",
minute: "Minuto"),
),
onChanged: (date) {},
),
),
),
when i exit from the first textfield both onFocusChange
are called so in the console i see:
data: ......
ora: ......
but in this case i expect to only receive:
data: ......
This happens because the focus listeners of both fields are fired even if the focus state doesn't change from true to false. At the moment it is fired even if the focus state was false and it's still false in the second text field.
Maybe you can keep the focusScopeListener
but fire it only when the focus state of the widget change from true to false or false to true? But i'm not sure if it can be the solution
@matteoberla I see.. Thank you very much! I recognized the problem. I will look for a way to fix it while working with Picker.
Thank you, then there's this part
It works fine but the only case where the selectedDate is not updated is when i insert an incomplete date (ex. 03 or 03/ ) in fact the validation doesn't return an error and so the selectedDate is not updated to null.
I would expect the selectedDate
to be set to null in that case
@matteoberla
I would expect the selectedDate to be set to null in that case
I'm trying to return null, is that a problem?
I modified it to be able to control focus on a per-field basis.
I also added a String type to the onFocusChanged
parameter.
I also added a BoardDateTimeTextController
to allow external users to update values in text fields.
final textController = BoardDateTimeTextController();
BoardDateTimeInputField(
controller: textController,
...
),
textController.setText('01.01.2024');
// or
textController.setDate(DateTime.now());
Still need to sort out the source code and comments.
I'm trying to return null, is that a problem?
Null is fine if the date inserted is not completed and so not valid
Rest of edits seems perfect, thank you!
Thank you for your cooperation! I will release the next version after I have organized the source code and verified that it works.
i've seen that if i insert a valid date ex. 03/04/2024 and then i insert ex. 03/ the retrieved value is not updated to null, but instead the old value is returned. same when i delete the whole text. same when the date format is not valid.
Thanks for letting me know! I guess the error handling wasn't working properly. It's fixed now.
Hi, it seems to be partially fixed.
input: 10/10/2024 console: data: 2024-10-10 00:00:00.000, 10/10/2024
input: "" console: data: null, "" (All correct)
input: 10/10/2024 console: data: 2024-10-10 00:00:00.000, 10/10/2024
input: 2000 console: data: 2024-10-10 00:00:00.000, 2000 (Here there's a problem as the date is not valid but it's not returned null)
Hi, it seems to be partially fixed.
input: 10/10/2024 console: data: 2024-10-10 00:00:00.000, 10/10/2024
input: "" console: data: null, "" (All correct)
input: 10/10/2024 console: data: 2024-10-10 00:00:00.000, 10/10/2024
input: 2000 console: data: 2024-10-10 00:00:00.000, 2000 (Here there's a problem as the date is not valid but it's not returned null)
Thank you. I have detected some problems while checking the operation and have corrected them. I've already fixed that issue as well.
Now it's working perfecty.
Thank you very much for your support, what you have done it's amazing, and you are always very kind.
Thank you very much, i'll start implementing it in my final code.
Thank you too for the great feature suggestions and tremendous support! Thanks to you, I have successfully implemented the feature. I will release it in v1.6.0, so please incorporate the official version!
I'm trying to set the initial value, i've never tried before but i'm getting this:
The following LateError was thrown building TypedInputDatetimeWidget: LateInitializationError: Field 'minimumDate' has not been initialized.
Even if i specify minimumDate the error is the same.
I've also tried as a workaround to call setText
when the widget is initialized but text is not set, if i call setText
from the press of a button is set correctly.
Am i doing something wrong?
I'm sorry. The initial values were processed in the wrong order. Fixed in v1.6.1.
Also found this
The following assertion was thrown while dispatching notifications for ValueNotifier<DateTime>:
setState() or markNeedsBuild() called during build.
This ItemWidget widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: ItemWidget-[LabeledGlobalKey<ItemWidgetState>#abde3]
dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#e2532]]
state: ItemWidgetState#97631(ticker inactive)
The widget which was currently being built when the offending call was made was: MediaQuery
MediaQueryData(size: Size(1814.0, 1284.0), devicePixelRatio: 1.0, textScaler: no scaling, platformBrightness: Brightness.light, padding: EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, systemGestureInsets: EdgeInsets.zero, alwaysUse24HourFormat: false, accessibleNavigation: false, highContrast: false, onOffSwitchLabels: false, disableAnimations: false, invertColors: false, boldText: false, navigationMode: traditional, gestureSettings: DeviceGestureSettings(touchSlop: null), displayFeatures: [])
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3 throw_
packages/flutter/src/widgets/framework.dart 5042:9 <fn>
packages/flutter/src/widgets/framework.dart 5053:14 markNeedsBuild
packages/flutter/src/widgets/framework.dart 1223:5 setState
packages/board_datetime_picker/src/ui/parts/item.dart 147:5 updateState
packages/board_datetime_picker/src/options/board_item_option.dart 255:28 updateState
packages/board_datetime_picker/src/options/board_item_option.dart 218:5 updateList
packages/board_datetime_picker/src/board_datetime_builder.dart 460:14 notify
packages/flutter/src/foundation/change_notifier.dart 433:24 notifyListeners
packages/flutter/src/foundation/change_notifier.dart 555:5 set value
packages/board_datetime_picker/src/board_datetime_builder.dart 576:5 changeDateTime
packages/board_datetime_picker/src/board_datetime_builder.dart 40:23 changeDate
packages/board_datetime_picker/src/board_datetime_input_field.dart 935:27 checkFormat
packages/board_datetime_picker/src/board_datetime_input_field.dart 504:7 <fn>
packages/flutter/src/foundation/change_notifier.dart 433:24 notifyListeners
packages/flutter/src/foundation/change_notifier.dart 555:5 set value
packages/board_datetime_picker/src/board_datetime_input_field.dart 59:5 setText
And it takes me to setText
, i'm using provider and i think that when notifyListeners()
is called the problem occurs
I could not reproduce it in my environment.
Do you have a sample using Provider
?
I will not have time after tomorrow to investigate that issue. Please wait a few minutes.
i can't show you a sample as i'm working on a quite complex project. What i'm doing is using as initial value a value from provider, i'm updating that value calling notifylisteners and so the widget rebuild, when it rebuilds the setText is called and i think that at this moment the error occurs, i'm tring to investigate too
I've noticed also that if the textfield has something in it, if i call setText
text is not overwritted
UPDATE
I've noticed something strange
-load the page
-call setText
by pressing a button which call controller.setText("12:00");
succesfully compiled text
-delete all text manually
-calling again settext
this time nothing happens
if i exit from the page and thus rebuild the widget the first time the value is set correctly, if i repeat the process same thing happens
I've noticed also that if the textfield has something in it, if i call
setText
text is not overwrittedUPDATE
I've noticed something strange
-load the page
-call
setText
by pressing a button which callcontroller.setText("12:00");
succesfully compiled text-delete all text manually
-calling again
settext
this time nothing happensif i exit from the page and thus rebuild the widget the first time the value is set correctly, if i repeat the process same thing happens
Please try using the v1.6.2 branch for this bug. It may be resolved.
Ok, i don't have much time so i'll probably test it tomorrow and let you know, i'll update you if i'll find something new
Trying to reproduce the error, i've found this:
======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for ValueNotifier<dynamic>:
A TextEditingController was used after being disposed.
Once you have called dispose() on a TextEditingController, it can no longer be used.
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3 throw_
packages/flutter/src/foundation/change_notifier.dart 179:9 <fn>
packages/flutter/src/foundation/change_notifier.dart 185:14 debugAssertNotDisposed
packages/flutter/src/foundation/change_notifier.dart 412:27 notifyListeners
packages/flutter/src/foundation/change_notifier.dart 555:5 set value
packages/flutter/src/widgets/editable_text.dart 240:11 set value
packages/flutter/src/widgets/editable_text.dart 225:5 set text
packages/board_datetime_picker/src/board_datetime_input_field.dart 924:5 checkFormat
packages/board_datetime_picker/src/board_datetime_input_field.dart 512:5 [_controllerListener]
packages/flutter/src/foundation/change_notifier.dart 433:24 notifyListeners
packages/flutter/src/foundation/change_notifier.dart 555:5 set value
packages/board_datetime_picker/src/board_datetime_input_field.dart 941:38 checkFormat
packages/board_datetime_picker/src/board_datetime_input_field.dart 302:9 [_focusListener]
packages/flutter/src/foundation/change_notifier.dart 433:24 notifyListeners
packages/flutter/src/widgets/focus_manager.dart 1089:5 [_notify]
packages/flutter/src/widgets/focus_manager.dart 1794:11 applyFocusChangesIfNeeded
dart-sdk/lib/async/zone.dart 1391:47 _rootRun
dart-sdk/lib/async/zone.dart 1301:19 run
dart-sdk/lib/async/zone.dart 1209:7 runGuarded
dart-sdk/lib/async/zone.dart 1249:23 <fn>
dart-sdk/lib/async/zone.dart 1399:13 _rootRun
dart-sdk/lib/async/zone.dart 1301:19 run
dart-sdk/lib/async/zone.dart 1209:7 runGuarded
dart-sdk/lib/async/zone.dart 1249:23 callback
dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7 <fn>
The ValueNotifier<dynamic> sending notification was: ValueNotifier<dynamic>#8789a(12:03)
====================================================================================================
This happens if you have declared the BoardDateTimeTextController
inside the provider instead of declaring it before build
method (declaring it before the build method doesn't return this error). It seems that the BoardDateTimeTextController
even when the widget rebuilds, still has an association to the TextEditingController
you are using inside the widget and while trying to change the value of the field the error occurs.
I think that yesterday's error was based on the same situation even if it wasn't the same.
Why am i declaring BoardDateTimeTextController
inside provider?
Actually i'm used to declare an object inside provider, and this object has the actual text value and a textController
associated to that specific text.
I always do like this with textcontrollers because notifyListeners()
rebuild widget and sometimes it can happens that the textcontroller lose it's focus because the controller it's regenerated and so the user has to tap again on the field in order to continue compiling.
Please try using the v1.6.2 branch for this bug. It may be resolved.
Successfully solved, thank you.
This happens if you have declared the BoardDateTimeTextController inside the provider instead of declaring it before build method (declaring it before the build method doesn't return this error). It seems that the BoardDateTimeTextController even when the widget rebuilds, still has an association to the TextEditingController you are using inside the widget and while trying to change the value of the field the error occurs.
Thank you. Please wait a moment while I investigate.
@matteoberla I do not know how to reproduce it. I have tried everything on my end and cannot reproduce it. I think there are various ways to implement Provider, so please let me know how to reproduce it. I can't seem to get it to reproduce with my possible implementation...
import 'package:board_datetime_picker/board_datetime_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProviderData extends ChangeNotifier {
DateTime date;
final textController = BoardDateTimeTextController();
ProviderData(this.date);
void setDate(DateTime d) {
date = d;
notifyListeners();
}
}
class ProviderParentWidget extends StatelessWidget {
const ProviderParentWidget({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ProviderData>(
create: (context) => ProviderData(DateTime.now()),
builder: (context, child) {
final data = Provider.of<ProviderData>(context);
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: BoardDateTimeInputField(
controller: data.textController,
pickerType: DateTimePickerType.datetime,
options: const BoardDateTimeOptions(
languages: BoardPickerLanguages.en(),
),
initialDate: data.date,
maximumDate: DateTime(2040),
minimumDate: DateTime(1900, 1, 1),
textStyle: Theme.of(context).textTheme.bodyMedium,
onChanged: (date) {},
onFocusChange: (val, date, text) {
if (date != null) {
data.setDate(date);
}
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
data.textController.setDate(DateTime.now());
},
),
);
},
);
}
}
Hi, I’ll try on Monday as I’m not in my office and let you know, i’ll try to modify your code to replicate the error case. Thank you for now.
Il giorno sab 6 apr 2024 alle 13:26 mytooyo @.***> ha scritto:
@matteoberla https://github.com/matteoberla I do not know how to reproduce it. I have tried everything on my end and cannot reproduce it. I think there are various ways to implement Provider, so please let me know how to reproduce it. I can't seem to get it to reproduce with my possible implementation...
import 'package:board_datetime_picker/board_datetime_picker.dart';import 'package:flutter/material.dart';import 'package:provider/provider.dart'; class ProviderData extends ChangeNotifier { DateTime date;
final textController = BoardDateTimeTextController();
ProviderData(this.date);
void setDate(DateTime d) { date = d; notifyListeners(); } } class ProviderParentWidget extends StatelessWidget { const ProviderParentWidget({super.key});
@override Widget build(BuildContext context) { return ChangeNotifierProvider
( create: (context) => ProviderData(DateTime.now()), builder: (context, child) { final data = Provider.of (context); return Scaffold( body: Align( alignment: Alignment.topCenter, child: BoardDateTimeInputField( controller: data.textController, pickerType: DateTimePickerType.datetime, options: const BoardDateTimeOptions( languages: BoardPickerLanguages.en(), ), initialDate: data.date, maximumDate: DateTime(2040), minimumDate: DateTime(1900, 1, 1), textStyle: Theme.of(context).textTheme.bodyMedium, onChanged: (date) {}, onFocusChange: (val, date, text) { if (date != null) { data.setDate(date); } }, ), ), floatingActionButton: FloatingActionButton( onPressed: () { data.textController.setDate(DateTime.now()); }, ), ); }, );
} }
— Reply to this email directly, view it on GitHub https://github.com/mytooyo/board_datetime_picker/issues/21#issuecomment-2041053550, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQP6TTV22B7YUJQDDEU7L6LY37LVZAVCNFSM6AAAAABFGXJX36VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBRGA2TGNJVGA . You are receiving this because you were mentioned.Message ID: @.***>
an error with this code:
import 'package:board_datetime_picker/board_datetime_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProviderData extends ChangeNotifier {
DateTime date = DateTime.now();
final textController = BoardDateTimeTextController();
void setDate(DateTime d) {
date = d;
notifyListeners();
}
}
class ProviderParentWidget extends StatelessWidget {
const ProviderParentWidget({super.key});
@override
Widget build(BuildContext context) {
var providerData = Provider.of<ProviderData>(context, listen: true);
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: BoardDateTimeInputField(
controller: providerData.textController,
pickerType: DateTimePickerType.datetime,
options: const BoardDateTimeOptions(
languages: BoardPickerLanguages.en(),
),
initialDate: providerData.date,
maximumDate: DateTime(2040),
minimumDate: DateTime(1900, 1, 1),
textStyle: Theme.of(context).textTheme.bodyMedium,
onChanged: (date) {},
onFocusChange: (val, date, text) {
if (date != null) {
providerData.setDate(date);
}
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
providerData.textController.setDate(DateTime.now());
},
),
);
}
}
doing this you have to wrap your MaterialApp
with a MultiProvider
widget and declare
ChangeNotifierProvider(
create: (_) => ProviderData(),
),
You only get the error if: -start from another page -go inside this page and change the date -go back -return inside and try to change the date
error is:
The following assertion was thrown while dispatching notifications for ValueNotifier<dynamic>:
A TextEditingController was used after being disposed.
Once you have called dispose() on a TextEditingController, it can no longer be used.
I'll try to reproduce the other error i got last week and let you know
In this case the error occurs after i change a character (in my case i've deleted "0" from "12:00" and inserted "1" so it becomes "12:01") and then onFocusChange
is fired.
Same changes needed as previous example
import 'package:board_datetime_picker/board_datetime_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class ProviderData extends ChangeNotifier {
DateTime start = DateTime(2024, 10, 11, 12, 0);
DateTime datetime = DateTime(2024, 10, 11, 12, 0);
BoardDateTimeTextController controller = BoardDateTimeTextController();
updateDateTime(DateTime date) {
start = date;
//controller.setText(start.toString());
controller.setText("${start.hour}:${start.minute}");
datetime = start;
//print(datetime);
notifyListeners();
}
}
class ProviderParentWidget extends StatelessWidget {
const ProviderParentWidget({super.key});
@override
Widget build(BuildContext context) {
var providerData = Provider.of<ProviderData>(context, listen: true);
return Scaffold(
body: Align(
alignment: Alignment.topCenter,
child: BoardDateTimeInputField(
controller: providerData.controller,
pickerType: DateTimePickerType.time,
options: const BoardDateTimeOptions(
languages: BoardPickerLanguages.en(),
),
initialDate: providerData.datetime,
maximumDate: DateTime(2040),
minimumDate: DateTime(1900, 1, 1),
textStyle: Theme.of(context).textTheme.bodyMedium,
onChanged: (date) {},
onFocusChange: (val, date, text) {
if (date != null) {
providerData.updateDateTime(date);
}
},
),
),
);
}
}
The error is printed as many times as i exit and enter from this page, so it seems that the textcontroller still has references to this widget and the boardController tries to update it.
error:
======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for ValueNotifier<dynamic>:
A TextEditingController was used after being disposed.
Once you have called dispose() on a TextEditingController, it can no longer be used.
for the other error i was facing i'll try to explain you what i was doing and the solution i've found.
I've a table with lots of rows, each row has a start time and an end time, both of them are BoardDateTimeInputField
and thus the user can edit them. If start>end or end<start i'm reversing them and so both notifyListeners()
, widget rebuilding and setText()
happens basically at the same moment, when reversing the time picker is showed but onFocusChange()
is making it disappearing, while setText()
(or maybe onChanged
) is tring to update the picker to the value inserted, setState is called but the widget is rebuilding so doesn't exists anymore and then the error occurs (I'm not sure but this is the only explaination i've found.
I've seen that by wrapping item.dart line 145, void updateState(Map<int, int> newMap, int newIndex)
like so:
void updateState(Map<int, int> newMap, int newIndex) {
if (!mounted) return;
WidgetsBinding.instance.addPostFrameCallback((_){
setState(() {
map = newMap;
if (selectedIndex != newIndex) {
selectedIndex = newIndex;
scrollController.animateToItem(
selectedIndex,
duration: duration,
curve: Curves.easeIn,
);
}
});
});
}
error doesn't occur anymore, hope it's a correct solution
UPDATE on textController error
seems to be fixed by adding
widget.controller?._notifier.removeListener(_controllerListener);
inside dispose()
I'm now investigating about onFocusChange
that seems to be called 2 times when i exit from the field.
_onFocused();
is called two times only if i press outside the field, while if i press enter when focused on the field works fine.
hi, I'm not getting why at line 301 of board_datetime_input_field.dart onFocusChanged
is called only if the text is not empty
if (textController.text.isNotEmpty) {
checkFormat(textController.text, complete: true);
// If the focus is out of focus, but the focus has moved to another InputField
final pf = FocusManager.instance.primaryFocus;
if (pf is BoardDateTimeInputFocusNode) {
closePicker();
widget.onFocusChange?.call(false, selectedDate, textController.text);
}
}
I think it should be called in any case
hi, i've noticed that with showPicker = false
the onFocusChanged
callback is never called, while if set to true it's called two times
@matteoberla
Hi, Sorry for the delay and thanks for doing the research.
I have already confirmed that the error is fixed by calling _notifier.removeListener
.
Also, the issue of onFocusChange
not being called when the picker is not displayed has been fixed.
However, I have not encountered an event where onFocusChange
is called twice.
Hi, i've been developing with your package and it works perfecty for mobile device. I'm now developing a web platform and your package is still working perfecty but the UX is very slow as the user can't select a date by compiling a textfield and maybe autocompile it even if all the info are not provided (like the year, minutes, seconds)
I've looked for a package that already handles all these things but i cannot find it, i've also noticed that flutter provides a date input field (https://api.flutter.dev/flutter/material/InputDatePickerFormField-class.html) but i think it's not what i was expecting, so 've tried to develop a widget that autocompile and accepts valid date/hours formats only.
I think it can be done better as i've faced many problems and i was wondering if you could take a look and maybe consider to add something similar to your package.
https://github.com/mytooyo/board_datetime_picker/assets/69200334/ed28964a-2bf4-44b2-9686-6a94e3db26b3
-For now it handles dd/mm/yyyy and HH:MM:ss, the autocompiling feature expects to receive at least dd/MM or HH, and the remaining data is automatically generated. -I was not able to set fixed length of the fields and automatically jump between the different parts of the dates so the user is forced to insert valid formats, but for now returning null if it's not valid is enough. -only digits are accepted and the date divider is always replaced by an "/" or ":" (i can input dots, slash, columns...)
I think it would be useful to add this type of widget as in many websites the date input is writable by the user using the keyboard and it's faster. it may become useful in some cases also for the mobile world as someone could prefere to let the user input the data.
Let me know what do you think about it.
P.S. i'm sorry to ask you for the second time, but i've noticed that the support of the intl package is now forced to 0.19 as i've asked last time but i've encoutered many versioning problems with other packages that expects the 0.18 and the developers are not going to update it for me. is it possible to support both 0.18 and 0.19 for you? Thanks