Recurrence editor in EJ2 TypeScript Scheduler control

31 Jan 202624 minutes to read

The Recurrence editor is integrated into Scheduler editor window by default, to process the recurrence rule generation for events. Tt can also be used as an individual component referring from the Scheduler repository to work with the recurrence related processes.

All the valid recurrence rule string mentioned in the iCalendar specifications are applicable to use with 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.

import { Schedule, Day, Week, WorkWeek, Month, Agenda, PopupOpenEventArgs } from '@syncfusion/ej2-schedule';
import { scheduleData } from './datasource.ts';

Schedule.Inject(Day, Week, WorkWeek, Month, Agenda);

let scheduleObj: Schedule = new Schedule({
    width: '100%', height: '550px',
    selectedDate: new Date(2018, 1, 15),
    eventSettings: { dataSource: scheduleData },
    popupOpen: (args: PopupOpenEventArgs): void => {
        if (args.type == 'Editor') {
            scheduleObj.eventWindow.recurrenceEditor.frequencies = ['none', 'daily', 'weekly'];
        }
    }
});
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/32.1.19/ej2-base/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-buttons/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-calendars/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-dropdowns/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-inputs/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-navigations/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-popups/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-schedule/styles/tailwind3.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js" type="text/javascript"></script>
    <script src="systemjs.config.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>LOADING....</div>
    <div id='container'>
        <div id="Schedule"></div>
    </div>
</body>

</html>
export let scheduleData: Object[] = [
    {
        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'
    }
];

The other properties available in recurrence editor are tabulated 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.

import { RecurrenceEditor } from '@syncfusion/ej2-schedule';

let recObject: RecurrenceEditor = new 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/32.1.19/ej2-base/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-buttons/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-calendars/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-dropdowns/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-inputs/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-navigations/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-popups/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-schedule/styles/tailwind3.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js" type="text/javascript"></script>
    <script src="systemjs.config.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>LOADING....</div>
    <div id='container'>
        <div id="RecurrenceEditor"></div>
    </div>
</body>

</html>

Accessing the recurrence rule string

The recurrence rule is generated based on the options selected from the recurrence editor and also it follows the iCalendar specifications. The generated recurrence rule string is a valid one to be used with the Scheduler event’s recurrence rule field.

The recurrence editor has a change event that triggers every time the fields are modified. The generated recurrence value can be accessed through the value option in the event argument.

import { RecurrenceEditor, RecurrenceEditorChangeEventArgs } from '@syncfusion/ej2-schedule';

let outputElement: HTMLElement = <HTMLElement>document.querySelector('#rule-output');

let recObject: RecurrenceEditor = new RecurrenceEditor({
    change: (args: RecurrenceEditorChangeEventArgs) => {
        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/32.1.19/ej2-base/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-buttons/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-calendars/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-dropdowns/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-inputs/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-navigations/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-popups/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-schedule/styles/tailwind3.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js" type="text/javascript"></script>
    <script src="systemjs.config.js" type="text/javascript"></script>
    <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/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>LOADING....</div>
    <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>
</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.

import { RecurrenceEditor, RecurrenceEditorChangeEventArgs } from '@syncfusion/ej2-schedule';

let outputElement: HTMLElement = <HTMLElement>document.querySelector('#rule-output');
let recObject: RecurrenceEditor = new RecurrenceEditor({
    change: (args: RecurrenceEditorChangeEventArgs) => {
        outputElement.innerText = args.value;
    }
});
recObject.appendTo('#RecurrenceEditor');
recObject.setRecurrenceRule('FREQ=DAILY;INTERVAL=2;COUNT=8');
outputElement.innerText = recObject.value as string;
<!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/32.1.19/ej2-base/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-buttons/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-calendars/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-dropdowns/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-inputs/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-navigations/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-popups/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-schedule/styles/tailwind3.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js" type="text/javascript"></script>
    <script src="systemjs.config.js" type="text/javascript"></script>
    <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/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>LOADING....</div>
    <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>
</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.
import { createElement } from '@syncfusion/ej2-base';
import { RecurrenceEditor, RecurrenceEditorChangeEventArgs } from '@syncfusion/ej2-schedule';

let outputElement: HTMLElement = <HTMLElement>document.querySelector('#rule-output');
let labelElement: HTMLElement = <HTMLElement>document.querySelector('#rule-label');
let recObject: RecurrenceEditor = new RecurrenceEditor({
  change: OnRecurrenceChange,
});
recObject.appendTo('#RecurrenceEditor');
let ruleString: string = 'FREQ=DAILY;INTERVAL=1';
recObject.setRecurrenceRule(ruleString);
labelElement.innerText = 'Date Collections';
outputElement.innerHTML = '';
let ruleStringDates: number[] = recObject.getRecurrenceDates(
  new Date(),
  ruleString
);

for (let index: number = 0; index < ruleStringDates.length; index++) {
  outputElement.appendChild(
    createElement('div', {
      innerHTML: new Date(ruleStringDates[index]).toString(),
    })
  );
}

function OnRecurrenceChange(args: RecurrenceEditorChangeEventArgs): void {
  if (args.value == '') {
    outputElement.innerText = 'Select Rule';
  } else {
    outputElement.innerHTML = '';
    let dates: number[] = recObject.getRecurrenceDates(new Date(), args.value);
    for (let index: number = 0; index < dates.length; index++) {
      outputElement.appendChild(
        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/32.1.19/ej2-base/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-buttons/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-calendars/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-dropdowns/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-inputs/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-navigations/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-popups/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-schedule/styles/tailwind3.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js" type="text/javascript"></script>
    <script src="systemjs.config.js" type="text/javascript"></script>
    <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/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>LOADING....</div>
    <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>
</body>

</html>

Recurrence date generation in server-side

Recurrence date instances can also be generated from server-side by manually referring the RecurrenceHelper class, which is specifically written and referenced from application end to handle this date generation process.

Refer here for the step-by-step procedure to achieve date generation in 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.

import { createElement } from '@syncfusion/ej2-base';
import { RecurrenceEditor } from '@syncfusion/ej2-schedule';
import { NumericTextBox, ChangeEventArgs } from '@syncfusion/ej2-inputs';

let numericValue: number = 10;
let numeric: NumericTextBox = new NumericTextBox({
  value: numericValue,
  change: numericFocus,
});
numeric.appendTo('#numeric');

let outputElement: HTMLElement = <HTMLElement>document.querySelector('#rule-output');
let labelElement: HTMLElement = <HTMLElement>document.querySelector('#rule-label');
let ruleString: string = 'FREQ=DAILY;INTERVAL=1; COUNT=30';
let recObject: RecurrenceEditor = new RecurrenceEditor();
let dates: number[] = 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 (let index: number = 0; index < dates.length; index++) {
  outputElement.appendChild(createElement('div', { innerHTML: new Date(dates[index]).toString() }));
}

function numericFocus(args: ChangeEventArgs): void {
  outputElement.innerHTML = '';
  let dates: number[] = recObject.getRecurrenceDates(
    new Date(2018, 0, 7, 10, 0),
    ruleString,
    '20180108T114224Z,20180110T114224Z',
    args.value,
    new Date(2018, 0, 7)
  );
  for (let index: number = 0; index < dates.length; index++) {
    outputElement.appendChild(
      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/32.1.19/ej2-base/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-buttons/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-calendars/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-dropdowns/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-inputs/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-navigations/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-popups/styles/tailwind3.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/32.1.19/ej2-schedule/styles/tailwind3.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js" type="text/javascript"></script>
    <script src="systemjs.config.js" type="text/javascript"></script>
    <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/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div id='loader'>LOADING....</div>
    <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>
</body>

</html>

Refer to the JavaScript Scheduler feature tour page for its groundbreaking feature representations. Also explore JavaScript Scheduler example to learn how to present and manipulate data.