Hi
I’m currently working on integrating a calendar component using the Syncfusion Scheduler and Firebase Firestore for data management. I’m having difficulty implementing data pagination based on the current view days in the agenda.
Initially, I attempted to manage the start date and end date using React state in the OnActionBegin event. However, setting state in this function caused the entire component to re-render, which led to unexpected bugs. To work around this issue, I implemented the DataManager, but I'm still struggling with updating it effectively when navigating between dates in the calendar.
I would appreciate guidance on how to effectively manage state and implement data pagination with Firestore to ensure smooth performance.
Hi, thank you for your response!
After reading your reply, I created a custom adapter that extends the urlAdaptor. As I mentioned, I'm using Firebase Firestore, so I don’t have a standard URL endpoint to call directly. Instead, I need to use Firebase's getDocs method with my collection name, rather than using fetch or any similar approach.
I implemented it this way, but when processQuery returns a promise, and then processResponse also returns a promise, the data doesn’t display in the calendar. Am I missing something or doing something wrong?
import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {
ScheduleComponent,
ViewsDirective,
ViewDirective,
Inject,
Agenda, navigating,
} from '@syncfusion/ej2-react-schedule';
import {registerLicense} from '@syncfusion/ej2-base';
import dayjs from 'dayjs';
import {PageHero} from "../components/Ui";
import {iconsNames} from "../components/Ui/CardGroups/consts";
import {DataManager} from '@syncfusion/ej2-data';
import {getDocsWhereMultiple, getModelSessionsForSession, mapAsync} from "../services";
import {COLLECTIONS} from "../constants/collections";
import {JsonAdaptor, UrlAdaptor} from "@syncfusion/ej2-data/src/adaptors";
registerLicense(process.env.REACT_APP_SYNCFUSION_LICENSE);
// Custom Firestore adaptor
class FirestoreAdaptor extends UrlAdaptor {
constructor() {
super();
}
// Override processQuery to fetch data from Firestore
async processQuery(dm, query) {
// Extract the start and end date from the query (this is usually passed from Syncfusion's scheduler)
const startDate = query.params.find(param => param.key === 'StartDate').value;
const endDate = query.params.find(param => param.key === 'EndDate').value;
// Prepare Firestore conditions
const conditions = [
{field: 'date', operator: '>=', value: new Date(startDate)},
{field: 'date', operator: '<=', value: new Date(endDate)}
];
const events = await getDocsWhereMultiple(COLLECTIONS.sessions, conditions);
return events.map(session => {
const startDate = new Date(dayjs(session.date).hour(9).minute(0).toDate());
return {
Id: session.id,
Subject: session.production,
StartTime: startDate,
EndTime: startDate,
IsAllDay: true,
};
});
}
convertToQueryString(request, query) {
return ''; // Not needed for Firestore
}
async processResponse(data) {
const res = await data;
return res
}
}
const Calendar = () => {
const [currentView, setCurrentView] = useState('Agenda');
const scheduleRef = useRef(null);
const [dataManager, setDataManager] = useState(null);
useEffect(() => {
// Initialize DataManager and fetch initial appointments
const initializedDateManager = async () => {
const manager = new DataManager(
{
adaptor: new FirestoreAdaptor()
})
await manager.ready;
setDataManager(manager);
};
initializedDateManager();
}, []);
return (
<div className="Calendar">
<PageHero loading={false} icon={iconsNames.calendar} header="לוח שנה"/>
<ScheduleComponent
ref={scheduleRef}
width='100%'
enablePersistence
height='500px'
selectedDate={new Date()}
enableRtl
readonly
eventSettings={{dataSource: dataManager}}
>
<ViewsDirective>
<ViewDirective option={currentView} isSelected enableLazyLoading/>
</ViewsDirective>
<Inject services={[Agenda]}/>
</ScheduleComponent>
</div>
);
};
export default Calendar;
const dataManager = new DataManager({ adaptor: new FirestoreAdaptor(), // Custom FirestoreAdaptor }); |
Hi again! I really appreciate your support. I tried to follow your instructions closely, but it still doesn't seem to work. I'm pasting the pseudocode here again to help clarify what I'm trying to implement. As I mentioned, when the process data returns a Promise, the appointments aren’t displaying.
import React, {useRef, useState} from 'react';
import {Agenda, Inject, ScheduleComponent, ViewDirective, ViewsDirective,} from '@syncfusion/ej2-react-schedule';
import {registerLicense} from '@syncfusion/ej2-base';
import dayjs from 'dayjs';
import {PageHero} from "../components/Ui";
import {iconsNames} from "../components/Ui/CardGroups/consts";
import {DataManager} from '@syncfusion/ej2-data';
import {getDocsWhereMultiple} from "../services";
import {COLLECTIONS} from "../constants/collections";
import {UrlAdaptor} from "@syncfusion/ej2-data/src/adaptors";
registerLicense(process.env.REACT_APP_SYNCFUSION_LICENSE);
// Custom Firestore adaptor
class FirestoreAdaptor extends UrlAdaptor {
constructor() {
super();
}
// Override processQuery to fetch data from Firestore
processQuery(dm, query) {
// Extract the start and end date from the query (this is usually passed from Syncfusion's scheduler)
const startDate = query.params.find(param => param.key === 'StartDate').value;
const endDate = query.params.find(param => param.key === 'EndDate').value;
// This is a mock demonstrating fetching documents from firebase firestore asynchronously.
return new Promise(resolve => {
resolve([{
Id: '1',
Subject: 'Paris',
StartTime: new Date(),
EndTime: new Date(),
}])
})
}
convertToQueryString(request, query) {
return ''; // Not needed for Firestore
}
async processResponse(data) {
const result = await data
return result
}
}
const dataManager = new DataManager(
{
adaptor: new FirestoreAdaptor()
});
const Calendar = () => {
const [currentView, setCurrentView] = useState('Agenda');
const scheduleRef = useRef(null);
return (
<div className="Calendar">
<PageHero loading={false} icon={iconsNames.calendar} header="לוח שנה"/>
<ScheduleComponent
ref={scheduleRef}
width='100%'
enablePersistence
height='500px'
selectedDate={new Date()}
enableRtl
readonly
eventSettings={{dataSource: dataManager}}
>
<ViewsDirective>
<ViewDirective option={currentView} isSelected enableLazyLoading/>
</ViewsDirective>
<Inject services={[Agenda]}/>
</ScheduleComponent>
</div>
);
};
export default Calendar;