Skip to content

Scheduler: update Appointment Edit Form how-to#8742

Open
vladaskorohodova wants to merge 3 commits into
DevExpress:25_2from
vladaskorohodova:scheduler-preserve-unsaved-changes25_2
Open

Scheduler: update Appointment Edit Form how-to#8742
vladaskorohodova wants to merge 3 commits into
DevExpress:25_2from
vladaskorohodova:scheduler-preserve-unsaved-changes25_2

Conversation

@vladaskorohodova
Copy link
Copy Markdown
Collaborator

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Scheduler how-to topic and an accompanying embedded demo that shows how to preserve unsaved appointment edit form changes by saving drafts to localStorage, restoring them on reopen, offering a “Discard Changes” action, and clearing drafts after successful saves.

Changes:

  • Added a new documentation topic describing draft save/restore/clear flows for jQuery, Angular, Vue, and React.
  • Added a new embedded demo (HTML/JS/CSS) to illustrate the behavior in the documentation simulator.
  • Implemented a “Discard Changes” button and popup hiding handling in the demo to persist drafts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 9 comments.

File Description
concepts/05 UI Components/Scheduler/030 Appointments/070 Appointment Edit Form/20 Preserve Unsaved Changes.md New how-to documentation for persisting unsaved appointment form edits via localStorage.
applications/UIWidgets/Guides/SchedulerPreserveChanges/index.js New demo logic for saving/restoring drafts, adding a discard button, and clearing drafts on save.
applications/UIWidgets/Guides/SchedulerPreserveChanges/index.html Demo host markup for the Scheduler instance.
applications/UIWidgets/Guides/SchedulerPreserveChanges/index.css Demo styling (Scheduler height and discard button item spacing/border).

@@ -0,0 +1,634 @@
When a user cancels the appointment edit form, unsaved changes are lost. To prevent data loss, you can save the current form state to `localStorage` when the form closes without saving, and restore the draft the next time the user opens the same appointment.

## Save a Draft on Cancel

The Scheduler does not expose a dedicated cancel event. To detect cancellation, listen to the Popup's `hiding` event inside `onAppointmentFormOpening`. Guard with an `isSaved` flag so that the handler fires only when the user closes the form without saving:
Comment on lines +44 to +55
onAppointmentFormOpening: function (e) {
const form = e.form;
const popup = e.popup;
const appointmentData = e.appointmentData || {};

isSaved = false;

popup.on('hiding', function () {
if (!isSaved) {
onCanceled(form, appointmentData);
}
});
Comment on lines +103 to +113
handleAppointmentFormOpening(e: DxSchedulerTypes.AppointmentFormOpeningEvent): void {
const { form, popup } = e;
const appointmentData = (e.appointmentData ?? {}) as Record<string, unknown>;

this.isSaved = false;

popup.on('hiding', () => {
if (!this.isSaved) {
this.onCanceled(form, appointmentData);
}
});
Comment on lines +156 to +167
function handleAppointmentFormOpening(e: DxSchedulerTypes.AppointmentFormOpeningEvent): void {
const { form, popup } = e;
const appointmentData = (e.appointmentData ?? {}) as Record<string, unknown>;

isSaved.value = false;

popup.on('hiding', () => {
if (!isSaved.value) {
onCanceled(form, appointmentData);
}
});
}
Comment on lines +206 to +215
const handleAppointmentFormOpening = useCallback(
(e: SchedulerTypes.AppointmentFormOpeningEvent) => {
const { form, popup } = e;
const appointmentData = (e.appointmentData ?? {}) as Record<string, unknown>;

isSaved.current = false;

popup.on('hiding', () => {
onCanceled(form, appointmentData, isSaved);
});

---


Comment on lines +2 to +42
const appointments = [
{
id: 1,
text: 'Team Stand-up',
startDate: new Date(2026, 4, 8, 9, 0),
endDate: new Date(2026, 4, 8, 9, 30),
description: 'Daily morning sync with the full team.'
},
{
id: 2,
text: 'Design Review',
startDate: new Date(2026, 4, 8, 11, 0),
endDate: new Date(2026, 4, 8, 12, 0),
description: 'Review latest UI mockups and prototypes.'
},
{
id: 3,
text: 'Sprint Planning',
startDate: new Date(2026, 4, 11, 14, 0),
endDate: new Date(2026, 4, 11, 16, 0),
description: 'Plan tasks for the upcoming sprint.'
},
{
id: 4,
text: 'Client Demo',
startDate: new Date(2026, 4, 12, 10, 0),
endDate: new Date(2026, 4, 12, 11, 30),
description: 'Showcase new features to the client.'
},
{
id: 5,
text: 'Retrospective',
startDate: new Date(2026, 4, 13, 15, 0),
endDate: new Date(2026, 4, 13, 16, 0),
description: 'Sprint retrospective — what went well / what to improve.'
}
];
const DRAFT_PREFIX = 'dx-scheduler-draft-';

function getDraftKey(appointmentId) {
return DRAFT_PREFIX + (appointmentId != null ? appointmentId : 'new');
Comment on lines +215 to +217
onAppointmentUpdating: function () {
isSaved = true;
clearDraft(currentAppointmentId);
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

concepts/05 UI Components/Scheduler/030 Appointments/070 Appointment Edit Form/20 Preserve Unsaved Changes.md:269

  • After the user clicks Discard Changes, the draft is removed, but the cancel-detection logic (Popup hiding handler guarded only by isSaved) can still run when the popup closes and immediately save a new draft again. Consider setting a separate flag (or temporarily disabling the hiding handler) when changes are discarded so closing the form does not recreate the draft.
                        onClick: function () {
                            localStorage.removeItem('dx-scheduler-draft-' + (appointmentId ?? 'new'));

                            form.option('formData', Object.assign({}, form.option('formData'), {
                                text: originalData.text,

Comment on lines +45 to +49
popup.on('hiding', function () {
if (!isSaved) {
onCanceled(form, appointmentData);
}
});
Comment on lines +162 to +166
onClick: function () {
clearDraft(currentAppointmentId);

form.option('formData', $.extend({}, form.option('formData'), {
text: originalData.text,
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants