Hello,
I am currently developing a scheduling component in a React/TypeScript project using Mobiscroll Scheduler, and I’ve encountered a problem with handling temporary events during drag-and-drop actions. Here is the issue and relevant code.
Problem Description
In my setup, users can drag an external event (defined as draggableEvent
) onto the Mobiscroll Scheduler. When the drag is in progress, a temporary event appears, which should become permanent only if the user confirms it by submitting a form with details. However, if the user cancels this form without saving, the temporary event still remains visible in the scheduler. This behavior leads to confusion, as the canceled event continues to occupy a time slot on the scheduler.
Goal
I need the temporary event to disappear if the user cancels the creation. My attempt to use Mobiscroll’s onEventCreateFailed
and onClose
callbacks to remove the event hasn’t been successful.
Key Code Sections
- Event Creation on Drag: When an event is dragged onto the scheduler,
handleEventCreate
initializes the temporary event with a 1.5-hour duration. Here’s the relevant code:
const handleEventCreate = useCallback((args: MbscEventCreateEvent) => {
const event = args.event;
// Récupération de l'heure de début du drop
const startDate = event.start;
// Calcul de l'heure de fin : 1h30 après le début
const endDate = addMinutes(startDate as Date, 90); // 90 minutes = 1h30
// Mise à jour des dates de l'événement
event.start = startDate;
event.end = endDate;
if (event.start && event.end) {
setDateStart(event.start);
setDateEnd(event.end);
}
setPopupEventTypeCode(event.id_code);
setPopupEventTypeDesc(event.description);
setPopupCollabId(event.resource?.toString() || "");
setDate([startDate!, endDate!]);
// Ouvrir la popup
setEdit(false);
setTempEvent(event);
setAnchor(args.domEvent.target);
setOpen(true);
}, );
useEffect(() => {
console.log(‘tempEvent:’, tempEvent);
}, [tempEvent]);
const handleEventCreated = useCallback(
(args: MbscEventCreatedEvent, inst: EventcalendarBase) => {
// Récupérer les informations de l’événement créé
console.log(“Event created:”, args.event);
// Mettre à jour initialValues.popupEventType avec la description de l’événement
setInitialValues((prevValues) => ({
…prevValues,
popupEventType: args.event.description,
}));
setToastText(args.event.title + " Ajouter");
setToastOpen(true);
setMyEvents((prevEvents) => […prevEvents, args.event]);
setTempEvent(undefined); // Nettoie l’événement temporaire
setForceReload(true);
},
);
const handleFailed = useCallback((event: MbscCalendarEvent) => {
setToastText('erreur lors de la création de l\'événement');
setForceReload(true);
setToastOpen(true);
}, );
const handleEventCreateFailed = useCallback(
(args: MbscEventCreateFailedEvent, inst: EventcalendarBase) => {
const { action, event, invalid, overlap, originEvent, source } = args;
console.error('Event creation failed:');
console.error('Action:', action);
console.error('Event:', event);
console.error('Invalid object:', invalid);
console.error('Overlapped event:', overlap);
console.error('Origin event:', originEvent);
console.error('Source:', source);
// Vider les variables si nécessaire
setPopupEventTypeCode('');
setPopupEventTypeDesc('');
setPopupCollabId('');
setEdit(false);
// setTempEvent(null);
handleFailed(event);
setForceReload(true);
},
[handleFailed]
);
const handleEventDeleted = useCallback(
(args: MbscEventDeletedEvent, inst: EventcalendarBase) => {
setToastText(currentEvent?.title + " Supprimer");
setToastOpen(true);
setCurrentEvent(undefined);
setForceReload(true);
},
);
const handlePageLoaded = useCallback(
(args: MbscPageLoadedEvent) => {
if (eventsLoaded) return;
const firstDay = startOfWeek(args.firstDay);
const lastDay = endOfWeek(args.lastDay);
const startDate = `${firstDay.getFullYear()}-${firstDay.getMonth() + 1}-${firstDay.getDate()}`;
const endDate = `${lastDay.getFullYear()}-${lastDay.getMonth() + 1}-${lastDay.getDate()}`;
PlanningSchedulerService.GetAllEventsByIdCollabs(
collabResources.map((collab) => collab.id),
startDate,
endDate
).then((result: { status: number; data: any }) => {
if (result.status === 200) {
const newEvents: MbscCalendarEvent[] = [];
for (let id_collaborateur in result.data) {
result.data[id_collaborateur].forEach((event: any) => {
newEvents.push({
id: event.id_plng,
resource: event.id_collaborateur,
start: event.start,
end: event.end,
allDay: event.fullday,
title: event.ticket,
color: event.activityCode.color,
descActivity: event.activityCode.description,
commentaire: event.commentaire,
adresse: event.adresse,
phone: event.phone,
status: event.status,
contact: event.contact,
env: event.environment.name,
envcolor: event.environment.color,
});
});
}
setMyEvents(newEvents);
setForceReload(false);
} else {
console.log("Error: ", result);
}
});
},
[ forceReload]
);
-
Attempted Cleanup on Cancel: To remove the temporary event on cancel, I created a clearTempEvent function, which should clear tempEvent from myEvents.
Here’s how I use it:const clearTempEvent = useCallback(() => {
if (tempEvent) {
setMyEvents((prevEvents) => prevEvents.filter(event => event.id !== tempEvent.id));
setTempEvent(undefined);
}
}, [tempEvent]);const onClose = useCallback(() => {
if (!isEdit) {
clearTempEvent(); // Clear on cancel
}
setOpen(false);
}, [isEdit, clearTempEvent]);
Also my component :
<Eventcalendar
className="rounded-lg"
view={calView}
renderHeader={customWithNavButtons}
resources={memoizedCollabResources}
renderResource={renderMyResource}
renderResourceEmpty={renderCustomResourceEmpty}
renderScheduleEvent={customScheduleEvent}
externalDrop={true}
externalDrag={true}
// renderBufferBefore={myBeforeBuffer}
data={myEvents}
dragToCreate={false}
dragToMove={false}
dragToResize={false}
showEventTooltip={true}
showEventBuffer={false}
onEventClick={handleEventClick}
onEventCreate={handleEventCreate}
onEventCreated={handleEventCreated}
onEventCreateFailed={handleEventCreateFailed}
onEventDeleted={handleEventDeleted}
onEventUpdated={handleEventUpdated}
onPageLoading={handlePageLoading}
onPageLoaded={handlePageLoaded}
invalid={disabledDates}
theme={isDarkTheme ? "customMaterial-dark" : "customMaterial"}
cssClass="md-switching-view-cont"
/>
<Popup
isOpen={isMainPopupOpen}
onClose={() => setMainPopupOpen(false)}
display="anchored"
anchor={anchor}
responsive={popupResponsive}
cssClass="md-tooltip"
>
<div onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
<div className="md-tooltip-header" style={headerStyle}>
<h4 className="dark:text-white text-black">
{currentEvent?.title ?? ""}
</h4>
</div>
<div className="md-tooltip-info">
<div className="md-tooltip-title">
Status:{" "}
<span className="md-tooltip-status md-tooltip-text">
{currentEvent?.status ?? "Pas de statut"}
</span>
<br />
Journée complète:{" "}
<span className="md-tooltip-fullday md-tooltip-text">
{currentEvent?.fullDay ? "Oui" : "Non"}
</span>
<p>Collaborateur : {selectedCollabName}</p>
</div>
<div className="md-tooltip-title">
Type d'activité:{" "}
<span className="md-tooltip-typeActivity md-tooltip-text">
{currentEvent?.descActivity}
</span>
</div>
<div className="md-tooltip-title">
Contact:{" "}
<span className="md-tooltip-contact md-tooltip-text">
{currentEvent?.contact}
</span>
<br />
Telephone:{" "}
<span className="md-tooltip-phone md-tooltip-text">
{currentEvent?.phone}
</span>
</div>
<div className="md-tooltip-title">
Adresse:{" "}
<span className="md-tooltip-location md-tooltip-text">
{currentEvent?.adresse}
</span>
</div>
<div className="md-tooltip-title">
Commentaire:{" "}
<span className="md-tooltip-reason md-tooltip-text">
{currentEvent?.commentaire}
</span>
</div>
<div className="md-tooltip-title">
Horaire:{" "}
<span className="md-tooltip-time md-tooltip-text">
{String(currentEvent?.start)} - {String(currentEvent?.end)}
</span>
</div>
</div>
</div>
<Button
onClick={() => {
setMainPopupOpen(false);
setOpen(true);
}}
>
Modifier
</Button>
</Popup>
<Popup
display="center"
fullScreen={true}
contentPadding={false}
headerText={headerText}
anchor={anchor}
isOpen={isOpen}
onClose={onClose}
responsive={popupResponsive}
>
- Current Behavior: Even with this configuration, the temporary event is not always removed. I’ve logged tempEvent to verify it, and it seems the event does not fully disappear from the UI when canceled.
Environment
React: 18.2.0
Mobiscroll React Package: 5.29.0
Question: Is there a recommended approach for cleaning up temporary events on cancel? Any guidance on ensuring that the event is fully removed from the scheduler’s UI and state would be appreciated.
Thank you for your assistance!