I am trying to implement a TableCalendar widget in my flutter app. This is old code so the events collection does not exist yet so the snapshot.hasdata should be "false" but it is goes into the "true" code.
Here is the code and the error message:

Why is it acting as if snapshot.hasdata = true?
Here is the code for the TableCalendar implementation:
// Example holidays
final Map<DateTime, List> _holidays = {
DateTime(2020, 1, 1): ['New Year\'s Day'],
DateTime(2020, 1, 6): ['Epiphany'],
DateTime(2020, 2, 14): ['Valentine\'s Day'],
DateTime(2020, 4, 21): ['Easter Sunday'],
DateTime(2020, 4, 22): ['Easter Monday'],
};
final kNow = DateTime.now();
final kFirstDay = DateTime(kNow.year, kNow.month - 3, kNow.day);
final kLastDay = DateTime(kNow.year, kNow.month + 12, kNow.day);
final _db = FirebaseFirestore.instance;
bool showSpinner = false;
DateTime? _selectedDay;
DateTime _focusedDay = DateTime.now();
LinkedHashMap<DateTime, List<Events>> kEvents =
LinkedHashMap<DateTime, List<Events>>();
class AppointmentCalendarScreen extends ConsumerStatefulWidget {
const AppointmentCalendarScreen({Key? key, this.title}) : super(key: key);
final String? title;
@override
ConsumerState<AppointmentCalendarScreen> createState() =>
_AppointmentCalendarScreenState();
}
class _AppointmentCalendarScreenState
extends ConsumerState<AppointmentCalendarScreen>
with TickerProviderStateMixin {
late final ValueNotifier<List<Events>> _selectedEvents;
Map<DateTime, List>? _selectedEventsMap;
late StreamController<Map<DateTime, List>> _streamController;
var eventDoc;
var trxnDoc;
Map<DateTime, List>? eventsMap;
@override
void initState() {
super.initState();
_streamController = StreamController();
_selectedDay = _focusedDay;
}
@override
void dispose() {
_selectedEvents.dispose();
_streamController.close();
super.dispose();
}
List<Events>? _getTrxnEventsForDay(DateTime day, List<Trxn>? trxns) {
DateTime? trxnDate;
DateTime trxnDateUTC;
for (int i = 0; i < trxnDoc.length; i++) {
if (trxnDoc[i].contractDate != null && trxnDoc[i].contractDate != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].contractDate);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc[i].contractDate);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
if (trxnDoc[i].closingDate != null && trxnDoc[i].closingDate != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].closingDate);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc[i].closingDate);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
if (trxnDoc[i].dueDiligence24b != null &&
trxnDoc[i].dueDiligence24b != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].dueDiligence24b);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc[i].dueDiligence24b);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
if (trxnDoc[i].financing24c != null && trxnDoc[i].financing24c != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].financing24c);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc[i].financing24c);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
if (trxnDoc[i].inspectionDate != null &&
trxnDoc[i].inspectionDate != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].inspectionDate);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc['inspectionDate']);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
if (trxnDoc[i].appraisalDate != null && trxnDoc[i].appraisalDate != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].appraisalDate);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc[i].appraisalDate);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
if (trxnDoc[i].sellerDisclosure24a != null &&
trxnDoc[i].sellerDisclosure24a != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].sellerDisclosure24a);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc[i].sellerDisclosure24a);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
if (trxnDoc[i].walkThroughDate != null &&
trxnDoc[i].walkThroughDate != "") {
trxnDate = DateTime.tryParse(trxnDoc[i].walkThroughDate);
trxnDateUTC = trxnDate!.toUtc();
if (day.year == trxnDate.year &&
day.day == trxnDate.day &&
day.month == trxnDate.month) {
List<Events> eventList = [];
eventList.add(trxnDoc[i].walkThroughDate);
(kEvents.putIfAbsent(trxnDateUTC, () => eventList));
}
}
//eventList.add(trxnDoc[i]);
//(kEvents.putIfAbsent(trxnDateUTC, () => eventList))??[];
}
return [];
}
List<Events> _getEventsForDay(DateTime day,
[List<Events>? events, List<Trxn>? trxns]) {
// kEvents is a linkedHashMap
// Calendar events
for (int i = 0; i < eventDoc.length; i++) {
DateTime eventDate = eventDoc[i].eventDate;
DateTime eventDateUTC = eventDate.toUtc();
if (day.yearListMap == eventDate.year &&
day.day == eventDate.day &&
day.month == eventDate.month) {
List<Events> eventList = [];
eventList.add(eventDoc[i]);
return (kEvents.putIfAbsent(eventDateUTC, () => eventList)) ?? [];
}
}
return [];
}
void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
if (!isSameDay(_selectedDay, selectedDay)) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
});
_selectedEvents.value = _getEventsForDay(selectedDay);
}
}
void _onVisibleDaysChanged(
DateTime first, DateTime last, CalendarFormat format) {}
void _onCalendarCreated(
DateTime first, DateTime last, CalendarFormat format) {}
@override
Widget build(BuildContext context) {
FirebaseFirestore _db = FirebaseFirestore.instance;
return Scaffold(
appBar: CustomAppBar(),
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _db
.collection('users')
.doc(ref.read(globalsNotifierProvider).currentUserId)
.collection('events')
.where('eventDate', isGreaterThanOrEqualTo: kFirstDay)
.where('eventDate', isLessThanOrEqualTo: kLastDay)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
List<Events> itemEvent = snapshot.data;
eventsMap = convertToMap(snapshot.data);
return _buildTableCalendar(snapshot.data as List<Events>?);
} else {
return const CircularProgressIndicator();
}
},
),
const SizedBox(height: 8.0),
ElevatedButton(
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
ref.read(globalsNotifierProvider.notifier).updatenewEvent(true);
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => AddEventScreen()));
setState(() {
showSpinner = false;
});
} catch (e) {
// todo: add better error handling
print(e);
}
},
child: const Text('Add Event'),
),
const SizedBox(height: 8.0),
Expanded(child: _buildEventList()),
],
),
);
}
// Simple TableCalendar configuration (using Styles)
Widget _buildTableCalendar([List<Events>? events, List<Trxn>? trxns]) {
return TableCalendar(
firstDay: kFirstDay,
lastDay: kLastDay,
focusedDay: _focusedDay,
selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
locale: 'en_US',
eventLoader: (day) {
return _getEventsForDay(day, events, trxns);
},
startingDayOfWeek: StartingDayOfWeek.sunday,
calendarStyle: CalendarStyle(
isTodayHighlighted: true,
selectedDecoration: BoxDecoration(color: Colors.deepOrange[400]),
todayDecoration: BoxDecoration(color: Colors.deepOrange[200]),
markerDecoration: const BoxDecoration(color: Colors.deepPurpleAccent),
outsideDaysVisible: false,
),
headerStyle: HeaderStyle(
formatButtonTextStyle:
const TextStyle().copyWith(color: Colors.white, fontSize: 15.0),
formatButtonDecoration: BoxDecoration(
color: Colors.deepOrange[400],
borderRadius: BorderRadius.circular(16.0),
),
),
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay; // update `_focusedDay` here as well
});
},
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
},
);
}
Widget _buildHolidaysMarker() {
return Icon(
Icons.add_box,
size: 20.0,
color: Colors.blueGrey[800],
);
}
Widget _buildEventList() {
final _db = FirebaseFirestore.instance;
return Container(
child: StreamBuilder<QuerySnapshot>(
stream: _db
.collection('users')
.doc(ref.read(globalsNotifierProvider).currentUserId)
.collection('event')
.where('eventDate',
isGreaterThanOrEqualTo: DateTime(
_focusedDay.year, _focusedDay.month, _focusedDay.day, 0, 0))
.where('eventDate',
isLessThan: DateTime(_focusedDay.year, _focusedDay.month,
_focusedDay.day + 1, 0, 0))
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: Text(
'Loading...',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
));
} else {
var doc = snapshot.data!.docs;
return ListView.builder(
itemCount: doc.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: ListTile(
isThreeLine: true,
title: Text(
'${doc[index]['eventName'] ?? 'n/a'}',
style: const TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueAccent),
),
subtitle: Text.rich(TextSpan(
text:
'${DateFormat('EE MM-dd-yyyy').format(doc[index]['eventDate']) ?? 'n/a'}\n'
'${DateFormat('h:mm a').format(doc[index]['eventStartTime']) ?? 'n/a'}, '
'Duration: ${doc[index]['eventDuration'] ?? 'n/a'} minutes',
children: <TextSpan>[
TextSpan(
text:
'\n${doc[index]['eventDescription'] ?? 'n/a'}',
style: const TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueGrey),
)
])),
//trailing: Text('MLS#: ${_event.mlsNumber ?? 'n/a'}'),
onTap: () {
ref
.read(globalsNotifierProvider.notifier)
.updatenewEvent(false);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => AddEventScreen()));
},
),
);
});
}
},
),
);
}
Map<DateTime, List>? convertToMap(List<Events> item) {
Map<DateTime, List>? result;
for (int i = 0; i < item.length; i++) {
Events data = item[i];
DateTime currentDate = DateTime(
data.eventDate!.year,
data.eventDate!.month,
data.eventDate!.day,
data.eventDate!.hour,
data.eventDate!.minute);
List eventNames = [];
for (int j = 0; j < item.length; j++) {
//create temp calendarItemData object.
Events temp = item[j];
//establish that the temp date is equal to the current date
if (data.eventDate == temp.eventDate) {
//add the event name to the event List.
eventNames.add(temp.eventName);
} //else continue
}
//add the date and the event to the map if the date is not contained in the map
if (result == null) {
result = {currentDate: eventNames};
} else {
result[currentDate] = eventNames;
}
return result;
}
}
}
UPDATE:
As the building of the widget goes through it's iterations of building, it eventually creates an instance of the snapshot. When I check to see of the snapshot.data is null I find that it is not but it has no docs, which is what I would expect. However, I see this when I hover over the ".data":
_delegate:
MethodChannelQuerySnapshot
_firestore:
FirebaseFirestore (FirebaseFirestore(app: [DEFAULT]))
docChanges:
List (0 items)
docs:
List (0 items)
hashCode:
479850384
metadata:
SnapshotMetadata
runtimeType:
Type (_JsonQuerySnapshot)
size:
0