Vueer
Vueer

Reputation: 1502

Have no access to a variable in Flutter Stateful Widget

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

Answers (2)

Alok
Alok

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

SempaiLeo
SempaiLeo

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

Related Questions