Loading and Displaying Events from Firestore in Flutter Calendar App
In Part 1 we learned to use Table Calendar package to display beautiful calendar in our application. In this second part of Flutter Calendar App tutorial, learn to integrate Firebase and then load and display event markers in calendar from Firestore database.
Integrate Firebase in App
Install firebase tools
npm install -g firebase-tools
install flutterfire CLI
pub global activate flutterfire_cli
Login to firebase cli
firebase login
and follow the steps.cd into your project folder
cd flutter_events_2023
Run
flutterfire configure
Select existing project or create new, I’m creating new project
Select the platforms to configure for, I left the default.
Select yes to upgrade android build settings
Now you are done setting up project and configuring flutter app
Setup Firestore with some Events
Go to https://console.firebase.google.com/ and select the project you added
flutter-fire-events
Select Cloud Firestore from the overview page to configure the database
Click on Create database
For the simplicity select
Start in test mode
, however for production you need to setup proper security rules. The security rules are not in the scope of this articleSelect the location suitable to your application and click enable
From the dashboard, click start collection and create a
events
collection and click NextAdd a first event, we are adding
title
,description
anddate
field. based on your requirement you can add as many information as you want.Click save and you should see the
events
collection.You can add more events by tapping on the
Add document
Initialize Firebase
Add
firebase_core
andcloud_firestore
dependency on top of existing onesflutter pub add firebase_core cloud_firestore
Run
flutterfire configure
again and select the project you previously createdflutter-fire-events
to make sure configurations are up to dateOpen
main.dart
and import firebase_core and the firebase_options created by the flutterfire_cliimport 'package:firebase_core/firebase_core.dart'; import './firebase_options.dart';
Update
main
function to initialize firebasevoid main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); runApp(const MyApp()); }
Now run the project to make sure everything is working. If you are running on iOS or macOS you might run into issues with minimum deployment target. If that happens open corresponding macOS or iOS project in Xcode and set the deployment target as minimum required by the firebase plugins. As of writing this it was
10.12
.
Loading & Displaying Events
First let’s define a model for our events data
class Event { final String title; final String? description; final DateTime date; final String id; Event({ required this.title, this.description, required this.date, required this.id, }); factory Event.fromFirestore(DocumentSnapshot<Map<String, dynamic>> snapshot, [SnapshotOptions? options]) { final data = snapshot.data()!; return Event( date: data['date'].toDate(), title: data['title'], description: data['description'], id: snapshot.id, ); } Map<String, Object?> toFirestore() { return { "date": Timestamp.fromDate(date), "title": title, "description": description }; } }
Update the fields as per your requirement.
The easiest way to provide events to the calendar is to use LinkedHashMap, so let’s define one in the StatefulWidget where we display our TableCalendar define and initialize
late Map<DateTime, List<Event>> _events; @override void initState() { super.initState(); _events = LinkedHashMap( equals: isSameDay, hashCode: getHashCode, ); //... }
The isSameDay function is provided by TableCalendar, but we need to define the getHashCode function as the follow
int getHashCode(DateTime key) { return key.day * 1000000 + key.month * 10000 + key.year; }
Just making sure we get unique hash code for each date.
Next, let’s write a function that will load events from our events collection and add it to
_events
_loadFirestoreEvents() async { final snap = await FirebaseFirestore.instance .collection('events') .withConverter( fromFirestore: Event.fromFirestore, toFirestore: (event, options) => event.toFirestore()) .get(); for (var doc in snap.docs) { final event = doc.data(); final day = DateTime.utc(event.date.year, event.date.month, event.date.day); if (_events[day] == null) { _events[day] = []; } _events[day]!.add(event); } setState(() {}); }
Don’t forget to call
_loadFirestoreEvents
ininitState
so that event’s are loaded in the beginning.Finally let’s define and provide
_getEventForTheDay
function to our calendar so that it can display event markersList _getEventsForTheDay(DateTime day) { return _events[day] ?? []; } // update table calendar to provide eventLoader property body: TableCalendar( eventLoader: _getEventsForTheDay, //... },
Now restart your application and you should see the event markers in the dates that you have added dummy events to your database for.
Conclusion
In this tutorial we learned how to configure firebase and load and display events from firebase in our application. In the further tutorials we will learn to further optimize the firebase query, load and display events of the selected date and also manage events (add, update, delete) from our application. You can find the completed source code in the p2-firestore-events
branch.
https://github.com/lohanidamodar/flutter_events_2023/tree/p2-firestore-events
Thank you for reading this tutorial. See you again in the next one.
Enjoyed? Tell your friends.