datetime_picker_formfield
datetime_picker_formfield copied to clipboard
Can't get text field to update on rebuild of form
I have a stateful widget that builds and displays a Form that contains several DateTimeField widgets. The first time the form is built the initialValue that I specify is correctly set for each DateTimeField. However, when the build method is called again (because one or more of the time values has changed externally) the new initialValue is not shown - it keeps what's there. It's as if the initialValue is being ignored totally. I suspect this is not a bug but a problem with the way I'm using the DateTimeField widget.
Here's a snippet from the build method where one of the DateTimeFields is created:
DateTimeField(
initialValue: DateTime(0, 0, 0, _data.awakeWindowStartInMinutesAfterMidnight ~/ 60, _data.awakeWindowStartInMinutesAfterMidnight % 60),
format: timeFormat,
decoration: new InputDecoration(
hintText: 'Use the time picker to set the wakeup time',
labelText: 'Daily Awake Window Start',
suffixIcon: null
),
readOnly: true,
showCursor: false,
onSaved: (DateTime value)
{
this._data.awakeWindowStartInMinutesAfterMidnight = value.hour * 60 + value.minute;
},
onShowPicker: (context, currentValue) async {
final time = await showTimePicker(
context: context,
initialTime: TimeOfDay.fromDateTime(currentValue ?? DateTime.now()),
);
return DateTimeField.convert(time);
},
),
I found the problem. I am now using a controller and it works.
what's the purpose of using TextEditingController when we should pass value by initialValue ?
Initial value can only be set once it would appear. I wanted to be able to update the displayed value on the fly if it changed by some external operation.
I know what you mean, I had very similar situation. Data is loaded from the storage, and date field is updated some milliseconds after UI widget is initialized. So I ended up with a code like this:
in widget:
final ValueNotifier<DateTime> controller;
in widget state:
final TextEditingController ctrl = TextEditingController();
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: widget.controller,
builder: (context, value, child) {
ctrl.text = (widget.controller.value!=null) ? dateFormat.format(widget.controller.value) : "";
return DateTimeField(
initialValue: widget.controller.value,
validator: widget.validator,
controller: ctrl,
...
EDIT: this above is actually bad idea
what is required to do: after modifying controller.value you just need to update controller.text too.