In this tutorial, you will learn how to build a real-time event scheduler by integrating DHTMLX Scheduler with Firebase Firestore. This integration provides seamless synchronization of event data between the Scheduler UI and the Firestore database: all updates happen live, across all the connected clients.
You can check the corresponding example on GitHub: DHTMLX Scheduler with Firebase Firestore Demo.
Let's start by creating a new project directory and initializing a fresh frontend project using Vite:
mkdir scheduler-firebase-demo
cd scheduler-firebase-demo
npm create vite@latest . -- --template vanilla
After Vite has set up the project, clear the src
folder to start fresh:
rm -rf src/*
Now, install the necessary dependencies:
npm i dhtmlx-scheduler firebase
First, create a Firebase project by implementing the following steps:
scheduler-firebase-demo
) and follow the setup promptsThen set up Firestore by completing the steps below:
After that, register your web app in the following way:
</>
to register a new web appscheduler-firebase-demo
)Finally, configure Firebase in your project as described below:
src/firebase.js
and paste your Firebase config, initializing Firebase and Firestore:path src/firebase.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "scheduler-firebase-demo.firebaseapp.com",
projectId: "scheduler-firebase-demo",
storageBucket: "scheduler-firebase-demo.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID",
measurementId: "YOUR_MEASUREMENT_ID"
};
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
export { db };
Replace all the placeholder values (such as YOUR_API_KEY
, etc.) with your actual Firebase project credentials.
npm i -g firebase-tools
To begin with, prepare your HTML container. Replace your index.html
content with the following:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Scheduler Firebase demo</title>
</head>
<body>
<div id="scheduler_here" class="dhx_cal_container"
style='width:100%; height: 800px;'></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Then, specify the main JavaScript logic by creating the src/main.js
file with the code provided below.
It connects the Scheduler UI with Firestore and handles real-time updates.
path src/main.js
import { scheduler } from "dhtmlx-scheduler";
import { db } from "./firebase.js";
import {
collection,
query,
onSnapshot,
addDoc,
deleteDoc,
orderBy,
doc,
updateDoc,
getDocs,
} from "firebase/firestore";
import "dhtmlx-scheduler/codebase/dhtmlxscheduler.css";
const { remoteUpdates } = scheduler.ext.liveUpdates;
scheduler.plugins({
recurring: true,
});
scheduler.config.header = [
"day",
"week",
"month",
"date",
"prev",
"today",
"next",
];
scheduler.init("scheduler_here", new Date(2025, 3, 20), "week");
const eventsRef = collection(db, "events");
scheduler.createDataProcessor(async function (entity, action, ev, id) {
switch (action) {
case "create":
{
const createdDoc = await addDoc(eventsRef, ev);
if (createdDoc.id) {
return { action: "inserted", tid: createdDoc.id };
}
}
break;
case "update":
{
return updateDoc(doc(db, "events", id), ev);
}
break;
case "delete":
{
const deletedDoc = await deleteDoc(doc(db, "events", id));
if (deletedDoc) {
return { action: "deleted" };
}
}
break;
}
});
// helper functions to process event data
const processEvent = (docSnapshot) => {
const event = docSnapshot.data();
event.id = docSnapshot.id;
return event;
};
// without it collection wouldn't call onSnapshot
const eventsQuery = query(eventsRef, orderBy("text", "desc"));
(async () => {
const EventsSnap = await getDocs(eventsQuery);
const bulkEvents = EventsSnap.docs.map((ev) => processEvent(ev));
scheduler.parse(bulkEvents);
watchRealtime();
})();
const watchRealtime = () => {
let EventsLoaded = false;
onSnapshot(eventsQuery, (querySnapshot) => {
if (!EventsLoaded) {
// first snapshot sends the current state
// we have already loaded it at the previous step
EventsLoaded = true;
return;
}
querySnapshot.docChanges().forEach((change) => {
// processes only the server-side changes
if (change.doc.metadata.hasPendingWrites) return;
const event = processEvent(change.doc);
switch (change.type) {
case "added":
remoteUpdates.events({ type: "add-event", event });
break;
case "modified":
remoteUpdates.events({ type: "update-event", event });
break;
case "removed":
remoteUpdates.events({ type: "delete-event", event });
break;
}
});
});
};
This code integrates the DHTMLX Scheduler library with Firebase Firestore to create a real-time, interactive event calendar in a JavaScript application. It synchronizes event data between the Scheduler UI and a Firestore database, ensuring that changes made in either of them are immediately reflected in the other. The code supports event creation, updates, deletions, and recurring events, leveraging Firestore's real-time capabilities.
scheduler.createDataProcessor: handles CRUD operations for Scheduler events by syncing them with Firestore:
processEvent(docSnapshot): converts a Firestore document snapshot into a Scheduler event object, attaching the document's ID.
(...)() IIFE : the initial data loading. Loads all existing events from Firestore into the Scheduler when the page loads, then starts listening to real-time updates.
watchRealtime: uses Firestore's onSnapshot
to listen to the changes in the events collection and updates the Scheduler UI in real time. The key points are:
remoteUpdates
onSnapshot(q, callback): in real time listens to the changes in the Firestore "events" collection, ordered by "text" descending, and applies the corresponding live updates to the Scheduler UI using remoteUpdates.events
for added, modified, or removed events.
Now you need to initialize the Firebase Hosting and Firestore. For this, you should:
1. From your project root, run the following command:
firebase init
Then implement the steps given below:
dist
(the Vite build output)2. Build your project by running the command below:
npm run build
3. Deploy to the Firebase Hosting with the following command:
firebase deploy
When the deployment is done, your hosting URL will be displayed in the console.
Back to top