Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(Scheduler): Add Recurrence article #2873

Merged
merged 6 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/scheduler/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 11 additions & 7 deletions components/scheduler/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
230 changes: 230 additions & 0 deletions components/scheduler/recurrence.md
Original file line number Diff line number Diff line change
@@ -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
<TelerikScheduler Data="@SchedulerData"
@bind-Date="@SchedulerDate"
@bind-View="@SchedulerView"
AllowCreate="true"
AllowDelete="true"
AllowUpdate="true"
OnCreate="@OnSchedulerCreate"
OnDelete="@OnSchedulerDelete"
OnUpdate="@OnSchedulerUpdate"
Height="99vh">
<SchedulerViews>
<SchedulerDayView StartTime="@SchedulerViewStartTime"
EndTime="@SchedulerViewEndTime" />
<SchedulerWeekView StartTime="@SchedulerViewStartTime"
EndTime="@SchedulerViewEndTime" />
<SchedulerMonthView />
</SchedulerViews>
<SchedulerSettings>
<SchedulerPopupEditSettings MaxHeight="99vh" />
</SchedulerSettings>
</TelerikScheduler>

@code {
private List<Appointment> 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<DateTime>()
{
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<DateTime>? 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)
9 changes: 3 additions & 6 deletions docs-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading