Recurrence Editor in JavaScript Scheduler
The Recurrence Editor is integrated into the Scheduler editor by default to generate recurrence rule strings for events. It can also be used as a standalone component.
All valid recurrence rule strings defined by the iCalendar specification are supported by the Recurrence Editor.
Customizing the repeat type option in editor
By default, there are 5 types of repeat options available in the Recurrence editor:
- Never
- Daily
- Weekly
- Monthly
- Yearly
The Recurrence editor can be customized to display only the specific repeat options such as Daily and Weekly options alone by setting the appropriate frequencies option.
var scheduleObj = new ej.schedule.Schedule({
width: '100%',
height: '550px',
selectedDate: new Date(2018, 1, 15),
popupOpen: function (args) {
if (args.type == 'Editor') {
scheduleObj.eventWindow.recurrenceEditor.frequencies = ['none', 'daily', 'weekly'];
}
},
eventSettings: { dataSource: scheduleData }
});
scheduleObj.appendTo('#Schedule');<!DOCTYPE html>
<html lang="en">
<head>
<title>Schedule Typescript Control</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Typescript Schedule Control">
<meta name="author" content="Syncfusion">
<link href="index.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-navigations/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-schedule/styles/bootstrap5.3.css" rel="stylesheet">
<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
<script src="es5-datasource.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<div id="Schedule"></div>
</div>
<script>
var ele = document.getElementById('container');
if (ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body>
</html>var scheduleData = [
{
Id: 1,
Subject: 'Explosion of Betelgeuse Star',
StartTime: new Date(2018, 1, 11, 9, 30),
EndTime: new Date(2018, 1, 11, 11, 0),
CategoryColor: '#1aaa55'
}, {
Id: 2,
Subject: 'Thule Air Crash Report',
StartTime: new Date(2018, 1, 12, 12, 0),
EndTime: new Date(2018, 1, 12, 14, 0),
CategoryColor: '#357cd2'
}, {
Id: 3,
Subject: 'Blue Moon Eclipse',
StartTime: new Date(2018, 1, 13, 9, 30),
EndTime: new Date(2018, 1, 13, 11, 0),
CategoryColor: '#7fa900'
}, {
Id: 4,
Subject: 'Meteor Showers in 2018',
StartTime: new Date(2018, 1, 14, 13, 0),
EndTime: new Date(2018, 1, 14, 14, 30),
CategoryColor: '#ea7a57'
}, {
Id: 5,
Subject: 'Milky Way as Melting pot',
StartTime: new Date(2018, 1, 15, 12, 0),
EndTime: new Date(2018, 1, 15, 14, 0),
CategoryColor: '#00bdae'
}, {
Id: 6,
Subject: 'Mysteries of Bermuda Triangle',
StartTime: new Date(2018, 1, 15, 9, 30),
EndTime: new Date(2018, 1, 15, 11, 0),
CategoryColor: '#f57f17'
}, {
Id: 7,
Subject: 'Glaciers and Snowflakes',
StartTime: new Date(2018, 1, 16, 11, 0),
EndTime: new Date(2018, 1, 16, 12, 30),
CategoryColor: '#1aaa55'
}, {
Id: 8,
Subject: 'Life on Mars',
StartTime: new Date(2018, 1, 17, 9, 0),
EndTime: new Date(2018, 1, 17, 10, 0),
CategoryColor: '#357cd2'
}, {
Id: 9,
Subject: 'Alien Civilization',
StartTime: new Date(2018, 1, 19, 11, 0),
EndTime: new Date(2018, 1, 19, 13, 0),
CategoryColor: '#7fa900'
}, {
Id: 10,
Subject: 'Wildlife Galleries',
StartTime: new Date(2018, 1, 21, 11, 0),
EndTime: new Date(2018, 1, 21, 13, 0),
CategoryColor: '#ea7a57'
}, {
Id: 11,
Subject: 'Best Photography 2018',
StartTime: new Date(2018, 1, 22, 9, 30),
EndTime: new Date(2018, 1, 22, 11, 0),
CategoryColor: '#00bdae'
}, {
Id: 12,
Subject: 'Smarter Puppies',
StartTime: new Date(2018, 1, 9, 10, 0),
EndTime: new Date(2018, 1, 9, 11, 30),
CategoryColor: '#f57f17'
}, {
Id: 13,
Subject: 'Myths of Andromeda Galaxy',
StartTime: new Date(2018, 1, 7, 10, 30),
EndTime: new Date(2018, 1, 7, 12, 30),
CategoryColor: '#1aaa55'
}, {
Id: 14,
Subject: 'Aliens vs Humans',
StartTime: new Date(2018, 1, 5, 10, 0),
EndTime: new Date(2018, 1, 5, 11, 30),
CategoryColor: '#357cd2'
}, {
Id: 15,
Subject: 'Facts of Humming Birds',
StartTime: new Date(2018, 1, 20, 9, 30),
EndTime: new Date(2018, 1, 20, 11, 0),
CategoryColor: '#7fa900'
}, {
Id: 16,
Subject: 'Sky Gazers',
StartTime: new Date(2018, 1, 23, 11, 0),
EndTime: new Date(2018, 1, 23, 13, 0),
CategoryColor: '#ea7a57'
}, {
Id: 17,
Subject: 'The Cycle of Seasons',
StartTime: new Date(2018, 1, 12, 5, 30),
EndTime: new Date(2018, 1, 12, 7, 30),
CategoryColor: '#00bdae'
}, {
Id: 18,
Subject: 'Space Galaxies and Planets',
StartTime: new Date(2018, 1, 12, 17, 0),
EndTime: new Date(2018, 1, 12, 18, 30),
CategoryColor: '#f57f17'
}, {
Id: 19,
Subject: 'Lifecycle of Bumblebee',
StartTime: new Date(2018, 1, 15, 6, 0),
EndTime: new Date(2018, 1, 15, 7, 30),
CategoryColor: '#7fa900'
}, {
Id: 20,
Subject: 'Sky Gazers',
StartTime: new Date(2018, 1, 15, 16, 0),
EndTime: new Date(2018, 1, 15, 18, 0),
CategoryColor: '#ea7a57'
}
];Other recurrence editor properties are listed below:
| Properties | Type | Description |
|---|---|---|
| firstDayOfWeek | number | Sets the first day of the week on recurrence editor. |
| startDate | Date | Sets the start date from which date the recurrence event starts. |
| dateFormat | string | Sets the specific date format on recurrence editor. |
| locale | string | Sets the locale to be applied on recurrence editor. |
| cssClass | string | Allows styling to be applied on recurrence editor with custom class names. |
| enableRtl | boolean | Allows recurrence editor to render in RTL mode. |
| minDate | Date | Sets the minimum date on recurrence editor. |
| maxDate | Date | Sets the maximum date on recurrence editor. |
| value | string | Sets the recurrence rule value on recurrence editor. |
| selectedType | number | Sets the specific repeat type on the recurrence editor. |
Customizing the End Type Option in Editor
By default, there are 3 types of end options available in the Recurrence editor:
- Never
- Until
- Count
The Recurrence editor can be customized to display only the specific end options, such as the Until and Count options alone, by setting the appropriate endTypes option.
var recObject = new ej.schedule.RecurrenceEditor({
frequencies: ['daily', 'weekly'],
endTypes: ['until', 'count']
});
recObject.appendTo('#RecurrenceEditor');<!DOCTYPE html>
<html lang="en">
<head>
<title>Schedule Typescript Control</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Typescript Schedule Control">
<meta name="author" content="Syncfusion">
<link href="index.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-navigations/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-schedule/styles/bootstrap5.3.css" rel="stylesheet">
<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
</head>
<body>
<div id='loader'>LOADING....</div>
<div id="container">
<div id="RecurrenceEditor"></div>
</div>
<script>
var ele = document.getElementById('container');
if (ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body>
</html>Accessing the recurrence rule string
The recurrence rule is generated from the selected editor options and follows the iCalendar specification. You can access the generated rule via the Recurrence Editor’s change event; the value is available in the event argument’s value property.
var outputElement = document.querySelector('#rule-output');
var recObject = new ej.schedule.RecurrenceEditor({
change: function (args) {
if (args.value == "") {
outputElement.innerText = 'Select Rule';
} else {
outputElement.innerText = args.value;
}
}
});
recObject.appendTo('#RecurrenceEditor');
outputElement.innerText = 'Select Rule';<!DOCTYPE html>
<html lang="en">
<head>
<title>Schedule Typescript Control</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Typescript Schedule Control">
<meta name="author" content="Syncfusion">
<link href="index.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-navigations/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-schedule/styles/bootstrap5.3.css" rel="stylesheet">
<style>
.recurrence-editor-wrap {
margin: 0 25%;
}
.rule-output-container {
height: auto;
border: 1px solid #969696;
}
#rule-output {
padding: 8px 4px;
text-align: center;
min-height: 20px;
overflow: hidden;
overflow-wrap: break-word;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<div style="padding-bottom:15px;">
<label id="rule-label">Rule Output</label>
<div class="rule-output-container">
<div id="rule-output"></div>
</div>
</div>
<div id="RecurrenceEditor"></div>
</div>
<script>
var ele = document.getElementById('container');
if (ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body>
</html>Set specific value on recurrence editor
The Recurrence editor can be displayed with specific options loaded initially based on a provided rule string. The fields of the recurrence editor will change their values accordingly when you provide a particular rule through the setRecurrenceRule method.
var outputElement = document.querySelector('#rule-output');
var recObject = new ej.schedule.RecurrenceEditor({
change: function (args) {
outputElement.innerText = args.value;
}
});
recObject.appendTo('#RecurrenceEditor');
recObject.setRecurrenceRule('FREQ=DAILY;INTERVAL=2;COUNT=8');
outputElement.innerText = recObject.value;<!DOCTYPE html>
<html lang="en">
<head>
<title>Schedule Typescript Control</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Typescript Schedule Control">
<meta name="author" content="Syncfusion">
<link href="index.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-navigations/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-schedule/styles/bootstrap5.3.css" rel="stylesheet">
<style>
.recurrence-editor-wrap {
margin: 0 25%;
}
.rule-output-container {
height: auto;
border: 1px solid #969696;
}
#rule-output {
padding: 8px 4px;
text-align: center;
min-height: 20px;
overflow: hidden;
overflow-wrap: break-word;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<div style="padding-bottom:15px;">
<label id="rule-label">Rule Output</label>
<div class="rule-output-container">
<div id="rule-output"></div>
</div>
</div>
<div id="RecurrenceEditor"></div>
</div>
<script>
var ele = document.getElementById('container');
if (ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body>
</html>Recurrence date generation
The recurrenceRule of an event can be parsed to generate the date instances on which that particular event will occur, using the getRecurrenceDates method. It generates the dates based on the recurrenceRule that we provide. The parameters to be provided for getRecurrenceDates method are as follows.
| Field name | Type | Description |
|---|---|---|
startDate |
Date | Appointment start date. |
rule |
String | Recurrence rule present in an event object. |
excludeDate |
String | Date collection (in ISO format) to be excluded. It is optional. |
maximumCount |
Number | Number of date count to be generated. It is optional. |
viewDate |
Date | Current view range’s first date. It is optional. |
var outputElement = document.querySelector('#rule-output');
var labelElement = document.querySelector('#rule-label');
var recObject = new ej.schedule.RecurrenceEditor({
change: OnRecurrenceChange,
});
recObject.appendTo('#RecurrenceEditor');
var ruleString = 'FREQ=DAILY;INTERVAL=1';
recObject.setRecurrenceRule(ruleString);
labelElement.innerText = 'Date Collections';
outputElement.innerHTML = '';
var ruleStringDates = recObject.getRecurrenceDates(new Date(), ruleString);
for (var index = 0; index < ruleStringDates.length; index++) {
outputElement.appendChild(
new ej.base.createElement('div', {
innerHTML: new Date(ruleStringDates[index]).toString(),
})
);
}
function OnRecurrenceChange(args) {
if (args.value == '') {
outputElement.innerText = 'Select Rule';
} else {
outputElement.innerHTML = '';
var dates = recObject.getRecurrenceDates(new Date(), args.value);
for (var index = 0; index < dates.length; index++) {
outputElement.appendChild(
new ej.base.createElement('div', {
innerHTML: new Date(dates[index]).toString(),
})
);
}
}
}<!DOCTYPE html>
<html lang="en">
<head>
<title>Schedule Typescript Control</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Typescript Schedule Control">
<meta name="author" content="Syncfusion">
<link href="index.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-navigations/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-schedule/styles/bootstrap5.3.css" rel="stylesheet">
<style>
.recurrence-editor-wrap {
margin: 0 25%;
}
.rule-output-container {
height: auto;
border: 1px solid #969696;
}
#rule-output {
padding: 8px 4px;
text-align: center;
min-height: 20px;
overflow: hidden;
overflow-wrap: break-word;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<div style="padding-bottom:15px;">
<label id="rule-label">Rule Output</label>
<div class="rule-output-container">
<div id="rule-output"></div>
</div>
</div>
<div id="RecurrenceEditor"></div>
</div>
<script>
var ele = document.getElementById('container');
if (ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body>
</html>Recurrence date generation in server-side
You can generate recurrence dates on the server by using the RecurrenceHelper class or equivalent server-side logic.
See the KB article for a step-by-step procedure: https://www.syncfusion.com/kb/10009/how-to-parse-the-recurrencerule-at-server-side
Restrict date generation with specific count
If the rule is given in the “NEVER ENDS” category, the maximum count can be specified to stop the date generation starting from the provided start date. To do so, provide the appropriate maximumCount value within the getRecurrenceDates method as shown in the following code example.
var numericValue = 10;
var numeric = new ej.inputs.NumericTextBox({
value: numericValue,
change: numericFocus,
});
numeric.appendTo('#numeric');
var outputElement = document.querySelector('#rule-output');
var labelElement = document.querySelector('#rule-label');
var ruleString = 'FREQ=DAILY;INTERVAL=1; COUNT=30';
var recObject = new ej.schedule.RecurrenceEditor();
var dates = recObject.getRecurrenceDates(new Date(2018, 0, 7, 10, 0), ruleString, '20180108T114224Z,20180110T114224Z', numericValue, new Date(2018, 0, 7));
labelElement.innerText = 'Date Collections';
outputElement.innerHTML = '';
for (var index = 0; index < dates.length; index++) {
outputElement.appendChild(new ej.base.createElement('div', { innerHTML: new Date(dates[index]).toString() }));
}
function numericFocus(args) {
outputElement.innerHTML = '';
var dates = recObject.getRecurrenceDates(
new Date(2018, 0, 7, 10, 0),
ruleString,
'20180108T114224Z,20180110T114224Z',
args.value,
new Date(2018, 0, 7)
);
for (var index = 0; index < dates.length; index++) {
outputElement.appendChild(
ej.base.createElement('div', {
innerHTML: new Date(dates[index]).toString(),
})
);
}
}<!DOCTYPE html>
<html lang="en">
<head>
<title>Schedule Typescript Control</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Typescript Schedule Control">
<meta name="author" content="Syncfusion">
<link href="index.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-calendars/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-navigations/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/bootstrap5.3.css" rel="stylesheet">
<link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-schedule/styles/bootstrap5.3.css" rel="stylesheet">
<style>
.recurrence-editor-wrap {
margin: 0 25%;
}
.rule-output-container {
height: auto;
border: 1px solid #969696;
}
#rule-output {
padding: 8px 4px;
text-align: center;
min-height: 20px;
overflow: hidden;
overflow-wrap: break-word;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<div style="padding-bottom:15px;">
<label id="rule-label">Rule Output</label>
<div class="rule-output-container">
<div id="rule-output"></div>
</div>
</div>
<div class="wrap">
<input id="numeric" type="text" />
</div>
</div>
<script>
var ele = document.getElementById('container');
if (ele) {
ele.style.visibility = "visible";
}
</script>
<script src="index.js" type="text/javascript"></script>
</body>
</html>Refer to the JavaScript Scheduler feature tour for an overview, and explore the Scheduler demo for practical examples.