I am new in create calender in flutter. I try to create table_calendar, and add event to the calender but I got an error.
The code I did:
Map<DateTime, List> _events = {};
DateTime _focusedDay = DateTime.now();
DateTime _selectedDate;
@override
void initState() {
_selectedDate = _focusedDay;
DateTime d = DateTime.utc(DateTime.now().year, DateTime.now().month, DateTime.now().day, 12);
_events[d] = [];
_events[d].add("Event A");
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TableCalendar(
focusedDay: _focusedDay,
onDaySelected: (selectedDay, focusedDay) {
if (!isSameDay(_selectedDate, selectedDay)) {
setState(() {
_selectedDate = selectedDay;
_focusedDay = focusedDay;
});
}
},
eventLoader: (day) {
return _events.keys.contains(day) ? _events[day] : [];
},
)
],
);
The error I got is: The following NoSuchMethodError was thrown building Calender(dirty, state: _CalenderState#3429f): The getter 'year' was called on null. Receiver: null Tried calling: year
CodePudding user response:
It looks like your main problem is this line in your initState()
:
DateTime d = DateTime.utc(DateTime.now().year, DateTime.now().month, DateTime.now().day, 12);
The eventLoader is passed DateTime
s at midnight (at 00:00:00.000). When you add "Event A" to your event map, the key you give it is a DateTime
for today at noon since you give it an hour parameter of 12. In the event loader, you check if there's a value in your event map with a key of today at midnight. Since there isn't, it thinks there's no event today.
You're also missing the firstDay
and lastDay
parameter for your TableCalendar
, which are both required.
It seems like the error you mentioned is coming from code outside of the snippet you posted. Your only use of the 'year' getter is DateTime.now().year
, which is perfectly valid.
Below is an example of the calendar widget with those two fixes applied. I also added several other small improvements to your code with comments explaining those improvements. Here's a link to an image showing the resulting calendar, which properly shows the event you added to today's date:
The resulting calendar running in an iOS simulator
class Calendar extends StatefulWidget {
const Calendar({Key? key}) : super(key: key);
@override
State<Calendar> createState() => _CalendarState();
}
class _CalendarState extends State<Calendar> {
final Map<DateTime, List> _events = {};
DateTime _focusedDay = DateTime.now();
// Instead of initializing in initState, just add the "late" modifier.
late DateTime _selectedDate = _focusedDay;
@override
void initState() {
// This is where your problem is. The event loader is passed DateTimes with
// the time component set to zero (midnight). d is set to noon. Just delete
// the argument of "12" for hours.
DateTime d = DateTime.utc(
DateTime.now().year,
DateTime.now().month,
DateTime.now().day,
);
// Just add "Event A" to the list on this line
_events[d] = ["Event A"];
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TableCalendar(
// Make sure you add the required arguments "firstDay" and "lastDay"
firstDay: DateTime(1970),
lastDay: DateTime.now(),
focusedDay: _focusedDay,
onDaySelected: (selectedDay, focusedDay) {
if (!isSameDay(_selectedDate, selectedDay)) {
setState(() {
_selectedDate = selectedDay;
_focusedDay = focusedDay;
});
}
},
eventLoader: (day) {
// Use a null aware operator "??" to make this line simpler. If
// _events[day] is null, return the empty list instead.
return _events[day] ?? [];
},
)
],
);
}
}