Skip to content

Commit f66528e

Browse files
committed
docs(Scheduler): add docs for recurrence edit mode
1 parent a12377a commit f66528e

File tree

2 files changed

+175
-1
lines changed

2 files changed

+175
-1
lines changed

components/scheduler/editing/edit-appointments.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Main events you need to implement so you can store the appointment information c
3434

3535
* `OnCreate` - fires when the user saves a new appointment, including an exception for a recurring appointment.
3636
* `OnUpdate` - fires when the user changes an existing appointment. Fires for the recurring appointment when an exception has been created for it.
37-
* `OnDelete` - fires when the user deletes and appointment (including a recurring appointment). You can also enable a [delete confirmation dialog](#delete-confirmation-dialog).
37+
* `OnDelete` - fires when the user deletes an appointment (including a recurring appointment). You can also enable a [delete confirmation dialog](#delete-confirmation-dialog).
3838

3939
There are two other events that you are not required to handle - you can use them to implement application logic:
4040

@@ -45,6 +45,8 @@ There are two other events that you are not required to handle - you can use the
4545
* `OnEdit` does not fire when the user drags to resize or move appointments, it fires only for the advanced edit form (double clicks on the appointment).
4646
* `OnCancel` - fires when the user clicks the `Cancel` button in the edit form or the `[x]` close button at the window titlebar to discard the changes they just made to an appointment.
4747

48+
The event arguments that are received by the `OnEdit`, `OnUpdate`, and `OnDelete` events include a `EditMode` property that indicates whether the user chose to delete the entire series (`SchedulerRecurrenceEditMode.Series`) or only a single occurrence (`SchedulerRecurrenceEditMode.Occurrence`). For detailed information and examples, see the [Handling Recurring Appointments in CRUD Events](slug:scheduler-recurrence#handling-recurring-appointments-in-crud-events) section.
49+
4850

4951
## User Experience
5052

components/scheduler/recurrence.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The Telerik Scheduler for Blazor supports displaying and editing of recurring ap
1515
* Configure the Scheduler for using recurring appointments.
1616
* Define recurrence rules and recurrence exceptions in the Scheduler data.
1717
* Edit recurring appointments and exceptions.
18+
* Handle editing and deleting recurring appointments with the recurrence context.
1819

1920
## Basics
2021

@@ -219,6 +220,177 @@ A single Scheduler data item defines one series of recurring appointments. Set t
219220
}
220221
````
221222

223+
## Handling Recurring Appointments in CRUD Events
224+
225+
When users edit, update, or delete a recurring appointment, the Scheduler prompts them to choose whether to modify only the current occurrence or the entire series. This choice is reflected in the `EditMode` property of the event arguments.
226+
227+
### RecurrenceEditMode Property
228+
229+
The `OnEdit`, `OnUpdate`, and `OnDelete` event handlers receive event arguments that include a `EditMode` property. This property indicates the user's choice when interacting with recurring appointments:
230+
231+
* `SchedulerRecurrenceEditMode.Series` - The user chose to edit or delete the entire series of recurring appointments.
232+
* `SchedulerRecurrenceEditMode.Occurrence` - The user chose to edit or delete only a single occurrence of the recurring appointment.
233+
234+
### Example
235+
236+
You can use the `EditMode` property to implement different logic based on whether the user is modifying a single occurrence or the entire series.
237+
238+
>caption Handle RecurrenceEditMode in OnUpdate and OnDelete events
239+
240+
````RAZOR
241+
<TelerikScheduler Data="@SchedulerData"
242+
@bind-Date="@SchedulerDate"
243+
@bind-View="@SchedulerView"
244+
AllowCreate="true"
245+
AllowDelete="true"
246+
AllowUpdate="true"
247+
OnCreate="@OnSchedulerCreate"
248+
OnEdit="@OnSchedulerEdit"
249+
OnDelete="@OnSchedulerDelete"
250+
OnUpdate="@OnSchedulerUpdate"
251+
Height="600px">
252+
<SchedulerViews>
253+
<SchedulerDayView StartTime="@SchedulerViewStartTime" />
254+
<SchedulerWeekView StartTime="@SchedulerViewStartTime" />
255+
<SchedulerMonthView />
256+
</SchedulerViews>
257+
</TelerikScheduler>
258+
259+
@code {
260+
private List<Appointment> SchedulerData { get; set; } = new();
261+
private DateTime SchedulerDate { get; set; } = DateTime.Today;
262+
private SchedulerView SchedulerView { get; set; } = SchedulerView.Week;
263+
private DateTime SchedulerViewStartTime { get; set; } = DateTime.Today.AddHours(8);
264+
265+
private void OnSchedulerCreate(SchedulerCreateEventArgs args)
266+
{
267+
Appointment item = (Appointment)args.Item;
268+
SchedulerData.Add(item);
269+
}
270+
271+
private void OnSchedulerEdit(SchedulerEditEventArgs args)
272+
{
273+
Appointment item = (Appointment)args.Item;
274+
275+
// OnEdit fires when the user is about to edit or create an appointment
276+
// SchedulerRecurrenceEditMode indicates whether they chose to edit the series or occurrence
277+
if (args.EditMode == SchedulerRecurrenceEditMode.Series)
278+
{
279+
Console.WriteLine("User chose to edit the entire series");
280+
// The item represents the recurring appointment with RecurrenceRule
281+
}
282+
else if (args.EditMode == SchedulerRecurrenceEditMode.Occurrence)
283+
{
284+
Console.WriteLine("User chose to edit only this occurrence");
285+
// The item will have RecurrenceId set to the parent appointment's Id
286+
Console.WriteLine($"Editing exception for recurring appointment: {item.RecurrenceId}");
287+
}
288+
289+
// You can cancel the event to prevent editing
290+
// args.IsCancelled = true;
291+
}
292+
293+
private void OnSchedulerUpdate(SchedulerUpdateEventArgs args)
294+
{
295+
Appointment item = (Appointment)args.Item;
296+
297+
if (args.EditMode == SchedulerRecurrenceEditMode.Series)
298+
{
299+
// User chose to update the entire series
300+
Console.WriteLine("Updating entire series of recurring appointments");
301+
302+
// Update the recurring appointment
303+
int originalItemIndex = SchedulerData.FindIndex(a => a.Id == item.Id);
304+
if (originalItemIndex >= 0)
305+
{
306+
SchedulerData[originalItemIndex] = item;
307+
}
308+
}
309+
else if (args.EditMode == SchedulerRecurrenceEditMode.Occurrence)
310+
{
311+
// User chose to update only this occurrence
312+
Console.WriteLine("Creating exception for single occurrence");
313+
314+
// This creates a new exception appointment
315+
// The item will have RecurrenceId pointing to the parent
316+
int originalItemIndex = SchedulerData.FindIndex(a => a.Id == item.Id);
317+
if (originalItemIndex >= 0)
318+
{
319+
SchedulerData[originalItemIndex] = item;
320+
}
321+
}
322+
}
323+
324+
private void OnSchedulerDelete(SchedulerDeleteEventArgs args)
325+
{
326+
Appointment item = (Appointment)args.Item;
327+
328+
if (args.EditMode == SchedulerRecurrenceEditMode.Series)
329+
{
330+
// User chose to delete the entire series
331+
Console.WriteLine("Deleting entire series");
332+
333+
// Remove the recurring appointment
334+
SchedulerData.Remove(item);
335+
336+
// Optionally, remove all exceptions for this series
337+
if (!string.IsNullOrEmpty(item.RecurrenceRule))
338+
{
339+
SchedulerData.RemoveAll(a => a.RecurrenceId?.Equals(item.Id) == true);
340+
}
341+
}
342+
else if (args.EditMode == SchedulerRecurrenceEditMode.Occurrence)
343+
{
344+
// User chose to delete only this occurrence
345+
Console.WriteLine("Deleting single occurrence");
346+
347+
if (item.RecurrenceId != null)
348+
{
349+
// This is already an exception, just remove it
350+
SchedulerData.Remove(item);
351+
352+
// Update the parent appointment's RecurrenceExceptions list
353+
var parentAppointment = SchedulerData.FirstOrDefault(a => a.Id.Equals(item.RecurrenceId));
354+
if (parentAppointment != null)
355+
{
356+
// Remove the exception date from the parent's list
357+
parentAppointment.RecurrenceExceptions?.Remove(item.Start);
358+
}
359+
}
360+
else
361+
{
362+
// This is a recurring appointment, create an exception
363+
// The Scheduler automatically adds the occurrence date to RecurrenceExceptions
364+
SchedulerData.Remove(item);
365+
}
366+
}
367+
}
368+
369+
public class Appointment
370+
{
371+
public Guid Id { get; set; }
372+
public string Title { get; set; } = string.Empty;
373+
public DateTime Start { get; set; }
374+
public DateTime End { get; set; }
375+
public bool IsAllDay { get; set; }
376+
public string RecurrenceRule { get; set; } = string.Empty;
377+
public List<DateTime>? RecurrenceExceptions { get; set; }
378+
public Guid? RecurrenceId { get; set; }
379+
380+
public Appointment()
381+
{
382+
Id = Guid.NewGuid();
383+
}
384+
}
385+
}
386+
````
387+
388+
### Important Considerations
389+
390+
* When the user edits or deletes a single occurrence of a recurring appointment, the Scheduler automatically manages the `RecurrenceExceptions` list and creates exception appointments with the appropriate `RecurrenceId`.
391+
* The `RecurrenceEditMode` property is only relevant when working with recurring appointments. For regular (non-recurring) appointments, this property is not used.
392+
* When creating a new appointment in a time slot that matches a recurring appointment, the user can choose to create an exception or a new independent appointment.
393+
222394
## Recurrence Editor Components
223395

224396
Telerik UI for Blazor provides standalone components that you can use to edit recurring appointments outside the Scheduler or in a [custom Scheduler popup edit form](slug:scheduler-kb-custom-edit-form).

0 commit comments

Comments
 (0)