Reputation: 1502
I try to use a variable in a stateful class in a constructor, for example in DateTime
. But I always get the error Only static members can be accessed in initializers.
. Why that?
Code Part
Here in DateFormat
I cannot use the variable currentDate
. Is there another possibility to have access to this variable?
DateTime currentDate;
final _form = GlobalKey<FormState>();
final _dateTimeController = TextEditingController(
text: DateFormat("HH:mm")
.format(DateTime(currentDate.year, currentDate.month, currentDate.day,
TimeOfDay.now().hour, TimeOfDay.now().minute))
.toString(),
);
var _editedCalendarEntry = CalendarEntry(
dateTime: DateTime.now(),
meetingPlace: "",
minutes: 0,
servicePartner: "",
status: "inactive",
timestamp: Timestamp.now());
@override
void initState() {
currentDate = widget.currentDate;
super.initState();
}
Entire Class
class AddCalendarEntry extends StatefulWidget {
final ScrollController scrollController;
final DateTime currentDate;
AddCalendarEntry({this.scrollController, this.currentDate});
@override
_AddCalendarEntryState createState() => _AddCalendarEntryState();
}
class _AddCalendarEntryState extends State<AddCalendarEntry> {
DateTime currentDate;
final _form = GlobalKey<FormState>();
final _dateTimeController = TextEditingController(
text: DateFormat("HH:mm")
.format(DateTime(currentDate.year, currentDate.month, currentDate.day,
TimeOfDay.now().hour, TimeOfDay.now().minute))
.toString(),
);
var _editedCalendarEntry = CalendarEntry(
dateTime: DateTime.now(),
meetingPlace: "",
minutes: 0,
servicePartner: "",
status: "inactive",
timestamp: Timestamp.now());
@override
void initState() {
currentDate = widget.currentDate;
super.initState();
}
@override
void dispose() {
_dateTimeController.dispose();
super.dispose();
}
Future<Null> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: widget.currentDate,
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101),
);
if (picked != null && picked != currentDate)
setState(() {
currentDate = picked;
print("Erfolgreich");
});
_editedCalendarEntry = CalendarEntry(
servicePartner: _editedCalendarEntry.servicePartner,
dateTime: DateTime(
picked.year,
picked.month,
picked.day,
_editedCalendarEntry.dateTime.hour,
_editedCalendarEntry.dateTime.minute),
meetingPlace: _editedCalendarEntry.meetingPlace,
minutes: _editedCalendarEntry.minutes,
status: _editedCalendarEntry.status);
}
void onTimeValueChanged(TimeOfDay time) {
HapticFeedback.lightImpact();
_editedCalendarEntry = CalendarEntry(
servicePartner: _editedCalendarEntry.servicePartner,
dateTime: DateTime(
_editedCalendarEntry.dateTime.year,
_editedCalendarEntry.dateTime.month,
_editedCalendarEntry.dateTime.day,
time.hour,
time.minute),
meetingPlace: _editedCalendarEntry.meetingPlace,
minutes: _editedCalendarEntry.minutes,
status: _editedCalendarEntry.status);
setState(() {
currentDate = _editedCalendarEntry.dateTime;
});
}
Future<Null> _selectTime(BuildContext context) async {
Navigator.of(context).push(
showPicker(
context: context,
value: TimeOfDay(hour: 9, minute: 0),
onChange: (time) => onTimeValueChanged(time),
is24HrFormat: true,
blurredBackground: false,
accentColor: Theme.of(context).primaryColor),
);
}
void _saveForm() {
_form.currentState.save();
print(_editedCalendarEntry.dateTime);
}
@override
Widget build(BuildContext context) {
return Material(
color: Theme.of(context).bottomSheetTheme.backgroundColor,
child: CupertinoPageScaffold(
backgroundColor: Theme.of(context).bottomSheetTheme.backgroundColor,
child: CustomScrollView(
controller: widget.scrollController,
physics: ClampingScrollPhysics(),
slivers: <Widget>[
CupertinoSliverNavigationBar(
backgroundColor:
Theme.of(context).bottomSheetTheme.backgroundColor,
automaticallyImplyLeading: false,
largeTitle: Text("Neuer Eintrag"),
border: Border.fromBorderSide(
BorderSide(color: Colors.transparent))),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
child: Form(
key: _form,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(width: 100, child: Text("Partner")),
Expanded(
child: TextFormField(
strutStyle: StrutStyle.disabled,
style: TextStyle(
color: Theme.of(context).primaryColor),
decoration: const InputDecoration(
border: InputBorder.none),
onSaved: (value) => {
_editedCalendarEntry = CalendarEntry(
servicePartner: value,
dateTime: _editedCalendarEntry.dateTime,
meetingPlace:
_editedCalendarEntry.meetingPlace,
minutes: _editedCalendarEntry.minutes,
status: _editedCalendarEntry.status)
},
),
),
],
),
Divider(
height: 0,
),
Row(
children: <Widget>[
Container(width: 100, child: Text("Datum")),
Expanded(
child: TextFormField(
initialValue: DateFormat('dd.MM.yyyy')
.format(currentDate)
.toString(),
strutStyle: StrutStyle.disabled,
readOnly: true,
style: TextStyle(
color: Theme.of(context).primaryColor),
decoration: const InputDecoration(
hintText: 'Datum',
border: InputBorder.none,
),
),
),
CupertinoButton(
onPressed: () => _selectDate(context),
child: Text('Auswählen'),
),
],
),
Divider(
height: 0,
),
Row(
children: <Widget>[
Container(width: 100, child: Text("Uhrzeit")),
Expanded(
child: TextFormField(
controller: _dateTimeController,
strutStyle: StrutStyle.disabled,
style: TextStyle(
color: Theme.of(context).primaryColor),
decoration: const InputDecoration(
hintText: 'Uhrzeit',
border: InputBorder.none),
),
),
CupertinoButton(
onPressed: () => _selectTime(context),
child: Text('Auswählen'),
),
],
),
CupertinoButton.filled(
child: Text("Speichern"), onPressed: _saveForm)
],
)),
),
),
)
],
),
),
);
}
}
Thanks for your help!
Upvotes: 0
Views: 68
Reputation: 8978
final _form = GlobalKey<FormState>();
// also TextEditingController data type should be initialized
// In your code, I cannot see that
final TextEditinController _dateTimeController = ...
...
is an initializer and there is no way to access this at this point. Initializers are executed before the constructor, but this is only allowed to be accessed after the call to the super constructor (implicit in your example) was completed. Therefore only in the constructor body (or later) access to this is allowed.
This is why you get the error message:
DateTime(currentDate.year, currentDate.month, currentDate.day, TimeOfDay.now().hour, TimeOfDay.now().minute)
accesses _dateTimeController
(this is implicit if you don't write it explicit).
What you can do is to initialize your _dateTimeController
inside your initState()
, after your currentDate
is initialzed
DateTime currentDate;
final _form = GlobalKey<FormState>();
final TextEditingController _dateTimeController;
@override
void initState() {
super.initState();
currentDate = widget.currentDate;
// here you do that to prevent that error
_dateTimeController = TextEditingController(
text: DateFormat("HH:mm")
.format(DateTime(currentDate.year, currentDate.month, currentDate.day,
TimeOfDay.now().hour, TimeOfDay.now().minute))
.toString(),
);
}
Upvotes: 1
Reputation: 344
You can add this inside initState. In the class you should have var _dateTimeController;˛
_dateTimeController = TextEditingController(
text: DateFormat("HH:mm")
.format(DateTime(currentDate.year, currentDate.month, currentDate.day,
TimeOfDay.now().hour, TimeOfDay.now().minute))
.toString(),
);
Upvotes: 0