diff --git a/components/scheduler/navigation.md b/components/scheduler/navigation.md index 9b0eed965..007b02431 100644 --- a/components/scheduler/navigation.md +++ b/components/scheduler/navigation.md @@ -5,7 +5,7 @@ description: Navigating the Scheduler for Blazor. slug: scheduler-navigation tags: telerik,blazor,scheduler,navigation published: true -position: 20 +position: 4 --- # Scheduler Navigation diff --git a/components/scheduler/overview.md b/components/scheduler/overview.md index 115c6b0aa..9e801c6c0 100644 --- a/components/scheduler/overview.md +++ b/components/scheduler/overview.md @@ -95,26 +95,30 @@ The [Scheduler offers different views](slug:scheduler-views-overview) that are s * Timeline (agenda) view -## Editing - -Users can [create, edit and delete Scheduler appointments](slug:scheduler-appointments-edit). The component provides you with the new information so you can store it to the underlying data source. - - ## Navigation The [Scheduler features extensive navigation](slug:scheduler-navigation), which can be both programmatic and managed by the end user. The component can change the currently visible time range, the current view, and toggle business hours only display. -## Templates +## Editing + +Users can [create, edit and delete Scheduler appointments](slug:scheduler-appointments-edit). The component provides you with the new information so you can store it to the underlying data source. -You can [customize the appointment appearance and content via Scheduler templates](slug:scheduler-templates-appointment). Another option is to use the [Scheduler `OnItemRender` event](slug:scheduler-events#itemrender). +## Recurrence + +The Scheduler can display and edit [recurring appointments and recurrence exceptions](slug:scheduler-recurrence). ## Resources and Grouping [Scheduler resources](slug:scheduler-resources) provide a way to associate and [group appointments](slug:scheduler-resource-grouping) by certain criteria, such as a meeting room, a participating person, or used equipment. +## Templates + +You can [customize the appointment appearance and content via Scheduler templates](slug:scheduler-templates-appointment). Another option is to use the [Scheduler `OnItemRender` event](slug:scheduler-events#itemrender). + + ## Events The [Scheduler component fires events](slug:scheduler-events) related to CRUD operations, item (appointment) clicks and user navigation. Use them to gain more information about user actions and enhance the component behavior. diff --git a/components/scheduler/recurrence.md b/components/scheduler/recurrence.md new file mode 100644 index 000000000..fb3ba38e3 --- /dev/null +++ b/components/scheduler/recurrence.md @@ -0,0 +1,230 @@ +--- +title: Recurrence +page_title: Scheduler Recurrence +description: Learn how to set up the Telerik Scheduler for Blazor to display and edit recurring appointments. +slug: scheduler-recurrence +tags: telerik, blazor, scheduler, recurrence +published: True +position: 7 +--- + +# Scheduler Recurrence + +The Telerik Scheduler for Blazor supports displaying and editing of recurring appointments and exceptions. This article describes how to: + +* Configure the Scheduler for using recurring appointments. +* Define recurrence rules and recurrence exceptions in the Scheduler data. +* Edit recurring appointments and exceptions. + +## Basics + +To display recurring appointments in the Scheduler component, the model class must implement [three recurrence-related properties](slug:scheduler-appointments-databinding#appointment-features): + +* `RecurrenceRule` +* `RecurrenceExceptions` +* `RecurrenceId` + +You can also [define custom property names](slug:scheduler-appointments-databinding#example-with-custom-field-names) through the respective Scheduler parameters: + +* `RecurrenceRuleField` +* `RecurrenceExceptionsField` +* `RecurrenceIdField` + +A single Scheduler data item defines one series of recurring appointments. Set the `RecurrenceRule` value, according to the [RFC5545 standard](https://tools.ietf.org/html/rfc5545#section-3.3.10). Then, if exceptions to the recurrence rule exist: + +* Each exception must be a separate data item. +* The `RecurrenceId` property of each exception must be equal to `Id` value of the recurring appointment. +* The `RecurrenceExceptions` property of the recurring appointment must contain the `Start` values of all occurrences, which are exceptions to the recurrence rule. The correct values are the original start `DateTime` values of the occurrences, which would apply if there were no exceptions. + +## Example + +>caption Bind Scheduler to recurring appointments and recurrence exceptions + +````RAZOR + + + + + + + + + + + +@code { + private List SchedulerData { get; set; } = new(); + + private DateTime SchedulerDate { get; set; } + + private SchedulerView SchedulerView { get; set; } = SchedulerView.Week; + + private DateTime SchedulerViewStartTime { get; set; } = DateTime.Today.AddHours(10); + private DateTime SchedulerViewEndTime { get; set; } = DateTime.Today.AddHours(19); + + private void OnSchedulerCreate(SchedulerCreateEventArgs args) + { + Appointment item = (Appointment)args.Item; + + SchedulerData.Add(item); + } + + private void OnSchedulerDelete(SchedulerDeleteEventArgs args) + { + Appointment item = (Appointment)args.Item; + + SchedulerData.Remove(item); + } + + private void OnSchedulerUpdate(SchedulerUpdateEventArgs args) + { + Appointment item = (Appointment)args.Item; + + int originalItemIndex = SchedulerData.FindIndex(a => a.Id == item.Id); + + if (originalItemIndex >= 0) + { + SchedulerData[originalItemIndex] = item; + } + } + + protected override void OnInitialized() + { + SchedulerDate = GetNextMonthStart(); + + DateTime mondayMidnight = GetStartDateTime(); + + SchedulerData.Add(new Appointment + { + Title = "Weekly team meeting", + Start = mondayMidnight.AddHours(10).AddMinutes(30), + End = mondayMidnight.AddHours(11).AddMinutes(30), + RecurrenceRule = "FREQ=WEEKLY;BYDAY=MO" + }); + + SchedulerData.Add(new Appointment + { + Title = "Workout at the gym", + Start = mondayMidnight.AddHours(17), + End = mondayMidnight.AddHours(18), + RecurrenceRule = "FREQ=WEEKLY;BYDAY=MO,WE,FR" + }); + + SchedulerData.Add(new Appointment + { + Title = "Quaterly meeting with manager", + Start = mondayMidnight.AddDays(3).AddHours(14).AddMinutes(30), + End = mondayMidnight.AddDays(3).AddHours(15).AddMinutes(30), + RecurrenceRule = "FREQ=MONTHLY;INTERVAL=3;COUNT=36;BYDAY=TH;BYSETPOS=1" + }); + + SchedulerData.Add(new Appointment + { + Title = "Pay monthly bills", + Start = new DateTime(mondayMidnight.Year, mondayMidnight.Month, 1), + End = new DateTime(mondayMidnight.Year, mondayMidnight.Month, 1), + IsAllDay = true, + RecurrenceRule = "FREQ=MONTHLY" + }); + + // Create a base recurring appointment. + // Exceptions are defined below. + Appointment dailyLunch = new Appointment + { + Title = "Daily lunch", + Start = mondayMidnight.AddHours(12), + End = mondayMidnight.AddHours(13), + RecurrenceRule = "FREQ=DAILY" + }; + SchedulerData.Add(dailyLunch); + + // Create exceptions to the base appointment. + int daysSinceMonday = SchedulerDate.DayOfWeek - DayOfWeek.Monday; + DateTime lastMonday = DateTime.SpecifyKind(SchedulerDate.AddDays(-daysSinceMonday), DateTimeKind.Unspecified); + + Appointment lateLunchException = new Appointment + { + Title = "Late lunch", + Start = lastMonday.AddHours(13), + End = lastMonday.AddHours(14), + RecurrenceId = dailyLunch.Id + }; + SchedulerData.Add(lateLunchException); + + Appointment earlyLunchException = new Appointment + { + Title = "Early lunch", + Start = lastMonday.AddDays(3).AddHours(11), + End = lastMonday.AddDays(3).AddHours(12), + RecurrenceId = dailyLunch.Id + + }; + SchedulerData.Add(earlyLunchException); + + // Relate the exceptions to the base appointment. + DateTime lateLunchOriginalStart = DateTime.SpecifyKind(lastMonday.AddHours(12), DateTimeKind.Unspecified); + DateTime earlyLunchOriginalStart = DateTime.SpecifyKind(lastMonday.AddDays(3).AddHours(12), DateTimeKind.Unspecified); + dailyLunch.RecurrenceExceptions = new List() + { + lateLunchOriginalStart, + earlyLunchOriginalStart + }; + } + + private DateTime GetNextMonthStart() + { + DateTime today = DateTime.Today; + + return new DateTime(today.Year, today.Month, 1).AddMonths(1); + } + + private DateTime GetStartDateTime() + { + DateTime firstDayOfLastYear = new DateTime(DateTime.Today.Year, 1, 1).AddYears(-1); + + return firstDayOfLastYear.AddDays(1 - (int)firstDayOfLastYear.DayOfWeek); + } + + public class Appointment + { + public Guid Id { get; set; } + + public string Title { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + + public DateTime Start { get; set; } + public DateTime End { get; set; } + public bool IsAllDay { get; set; } + + public string RecurrenceRule { get; set; } = string.Empty; + public List? RecurrenceExceptions { get; set; } + public object? RecurrenceId { get; set; } + + public Appointment() + { + var rand = new Random(); + Id = Guid.NewGuid(); + } + } +} +```` + +## Next Steps + +* [Enable Scheduler Editing](slug:scheduler-appointments-edit) + +## See Also + +* [Live Demo: Scheduler Recurring Appointments](https://demos.telerik.com/blazor-ui/scheduler/recurring-appointments) +* [Scheduler API Reference](slug:Telerik.Blazor.Components.TelerikScheduler-1) diff --git a/docs-builder.yml b/docs-builder.yml index ed60ada75..e09851942 100644 --- a/docs-builder.yml +++ b/docs-builder.yml @@ -312,16 +312,13 @@ meta: position: 80 "*components/scheduler/templates": title: Templates - position: 10 + position: 35 "*components/scheduler/views": title: Views - position: 5 + position: 3 "*components/scheduler/editing": title: Editing - position: 3 - "*components/scheduler/appointments": - title: Appointments - position: 2 + position: 5 "*components/menu/data-binding": title: Data Binding position: 2