Editor template in Angular Schedule component
9 Oct 202524 minutes to read
The Scheduler component utilizes popups and dialogs to display notifications and provides an editor window with event fields to simplify appointment creation and editing. The editor window and its fields can be easily customized, and validation rules can be applied as needed.
Event editor
The editor window opens on the Scheduler when a cell or event is double-clicked. When a cell is double-clicked, the editor window appears in “Add new” mode. When an event is double-clicked, it opens in “Edit” mode.
On mobile devices, the detailed editor window opens in edit mode by clicking the edit icon on the popup that appears after tapping an event once. To open the editor in add mode, tap a cell to display a +
indicator, then tap again to open the editor window.
To prevent the editor window from opening, render the Scheduler in
readonly
mode or use code customization within thepopupOpen
event.
How to change the editor window header title and text of footer buttons
You can modify the header title and the text of the footer buttons in the editor window by updating the corresponding localized word collection in the Scheduler.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { L10n } from '@syncfusion/ej2-base';
import { Component } from '@angular/core';
import { EventSettingsModel,TimelineViewsService } from '@syncfusion/ej2-angular-schedule';
import { scheduleData} from './datasource';
L10n.load({
'en-US': {
'schedule': {
'saveButton': 'Add',
'cancelButton': 'Close',
'deleteButton': 'Remove',
'newEvent': 'Add Event',
},
}
});
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
standalone: true,
selector: 'app-root',
providers: [DayService, WeekService, TimelineViewsService, MonthService, AgendaService, WorkWeekService, MonthAgendaService],
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['TimelineDay', 'Day', 'Week', 'Month', 'Agenda'];
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to change the label text of default editor fields
To change the default labels such as “Subject,” “Location,” and other field names, use the title
property within the field option of eventSettings
.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { WorkWeekService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel, DayService, WeekService, TimelineViewsService, MonthService, AgendaService } from '@syncfusion/ej2-angular-schedule';
import { scheduleData} from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService,
TimelineViewsService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'TimelineWeek', 'Month', 'Agenda'];
public eventSettings: EventSettingsModel = {
dataSource: scheduleData,
fields: {
id: 'Id',
subject: { name: 'Subject', title: 'Event Name' },
location: { name: 'Location', title: 'Event Location'},
description: { name: 'Description', title: 'Event Description' },
startTime: { name: 'StartTime', title: 'Start Duration' },
endTime: { name: 'EndTime', title: 'End Duration' }
}
};
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Field validation
You can validate the required fields in the editor window on the client side before submitting, by adding appropriate validation rules to each field. Appointment fields can accept both string
and object
types. To apply validations, specify object values for the event fields.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel} from '@syncfusion/ej2-angular-schedule';
import { scheduleData} from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
standalone: true,
selector: 'app-root',
providers: [DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService],
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings'></ejs-schedule>`
})
export class AppComponent {
minValidation: (args: { [key: string]: string }) => boolean = (args: { [key: string]: string }) => {
return args['value'].length >= 5;
};
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month', 'Agenda'];
public eventSettings: EventSettingsModel = {
dataSource: scheduleData,
fields: {
id: 'Id',
subject: { name: 'Subject', validation: { required: true } },
location: { name: 'Location', validation: { required: true } },
description: {
name: 'Description', validation: {
required: true, minLength: [this.minValidation, 'Need atleast 5 letters to be entered']
}
},
startTime: { name: 'StartTime', validation: { required: true } },
endTime: { name: 'EndTime', validation: { required: true } }
}
};
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
See form validation documentation for applicable validation rules.
Adding additional fields to the default editor
The additional fields can be added to the default event editor by making use of the popupOpen
event which gets triggered before the event editor opens on the Scheduler. The popupOpen
is a client-side event that triggers before any of the generic popups opens on the Scheduler. The additional field (any of the form elements) should be added with a common class name e-field
, so as to handle and process those additional data along with the default event object. In the following example, an additional field Event Type
has been added to the default event editor and its value is processed accordingly.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { createElement } from '@syncfusion/ej2-base';
import { EventSettingsModel, PopupOpenEventArgs } from '@syncfusion/ej2-angular-schedule';
import { eventsData} from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' (popupOpen)='onPopupOpen($event)'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public eventSettings: EventSettingsModel = {
dataSource: eventsData
};
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'Editor') {
// Create required custom elements in initial time
if (!args.element.querySelector('.custom-field-row')) {
let row: HTMLElement = createElement('div', { className: 'custom-field-row' });
let formElement: HTMLElement = args.element.querySelector('.e-schedule-form') as HTMLElement;
formElement.firstChild?.insertBefore(row, args.element.querySelector('.e-title-location-row'));
let container: HTMLElement = createElement('div', { className: 'custom-field-container' });
let inputEle: HTMLInputElement = createElement('input', {
className: 'e-field', attrs: { name: 'EventType' }
}) as HTMLInputElement;
container.appendChild(inputEle);
row.appendChild(container);
let dropDownList: DropDownList = new DropDownList({
dataSource: [
{ text: 'Public Event', value: 'public-event' },
{ text: 'Maintenance', value: 'maintenance' },
{ text: 'Commercial Event', value: 'commercial-event' },
{ text: 'Family Event', value: 'family-event' }
],
fields: { text: 'text', value: 'value' },
value: (<{ [key: string]: Object; }>(args.data))['EventType'] as string,
floatLabelType: 'Always', placeholder: 'Event Type'
});
dropDownList.appendTo(inputEle);
inputEle.setAttribute('name', 'EventType');
}
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to prevent the default focus of the editor widow
By default, when the editor window opens, focus is set to the subject
field. You can prevent this default focusing behavior using the popupOpen
event, as shown in the following code example.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ViewChild } from '@angular/core';
import { EventSettingsModel,PopupOpenEventArgs, ScheduleComponent } from '@syncfusion/ej2-angular-schedule';
import { eventsData} from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule #scheduleObj width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' (popupOpen)='onPopupOpen($event)'></ejs-schedule>`
})
export class AppComponent {
@ViewChild("scheduleObj")
public scheduleObj?: ScheduleComponent;
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public eventSettings: EventSettingsModel = {
dataSource: eventsData
};
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'Editor') {
let dialog = (args.element as any).ej2_instances[0];
dialog.open = function(args : any) {
this.scheduleObj.eventBase.focusElement();
};
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Customizing the default time duration in the editor window
The default event editor calculates start and end time durations based on the interval
value set in the timeScale
property. By default, the interval
value is set to 60 minutes, so the time difference in the event editor is 60 minutes. You can change this duration by updating the duration
option within the popupOpen
event.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel, PopupOpenEventArgs } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' (popupOpen)='onPopupOpen($event)'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'Editor') {
args.duration = 60;
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to prevent the display of editor and quick popups
You can prevent the display of editor and quick popup windows by setting the cancel
option to true
within the popupOpen
event.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel, PopupOpenEventArgs } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' (popupOpen)='onPopupOpen($event)'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'Editor' || args.type === 'QuickInfo') {
args.cancel = true;
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
You can also prevent only specific popups by checking the popup type within the popupOpen
event. The following table details the available popup types:
Type | Description |
---|---|
Editor | For Detailed editor window. |
QuickInfo | For Quick popup which opens on cell click. |
EditEventInfo | For Quick popup which opens on event click. |
ViewEventInfo | For Quick popup which opens on responsive mode. |
EventContainer | For more event indicator popup. |
RecurrenceAlert | For edit recurrence event alert popup. |
DeleteAlert | For delete confirmation popup. |
ValidationAlert | For validation alert popup. |
RecurrenceValidationAlert | For recurrence validation alert popup. |
How to prevent the display of editor in cell double click
You can prevent the editor from appearing by handling the cellDoubleClick event and setting the cancel
option to true
.
[src/app/app.component.ts]
import { Component } from '@angular/core';
import { scheduleData } from './data';
import { extend } from '@syncfusion/ej2-base';
import { EventSettingsModel, View, DayService, WeekService, WorkWeekService, MonthService, AgendaService, CellClickEventArgs } from '@syncfusion/ej2-angular-schedule';
@Component({
// tslint:disable-next-line:component-selector
selector: 'app-root',
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' (cellDoubleClick)='onCellDoubleClick($event)'></ejs-schedule>`,
/* custom code end*/
providers: [
DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService
],
})
export class AppComponent {
public data: Record<string, any>[] = ([] = extend([],scheduleData,null,true) as Record<string, any>[]);
public selectedDate: Date = new Date(2021, 0, 10);
public eventSettings: EventSettingsModel = { dataSource: this.data };
public currentView: View = 'Week';
public onCellDoubleClick(args: CellClickEventArgs): void {
args.cancel = true;
// Implement custom dialog if needed
}
}
Customizing timezone collection in the editor window
By default, the editor window displays built-in timezone collections. You can customize these using the timezoneDataSource
property with a collection of TimezoneFields
data.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel, TimelineMonthService } from '@syncfusion/ej2-angular-schedule';
@Component({
imports: [
ScheduleModule,
ButtonModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService,
TimelineMonthService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]="selectedDate" [eventSettings]="eventSettings" ></ejs-schedule>`
})
export class AppComponent {
public data: object[] = [{
Id: 1,
Subject: 'Explosion of Betelgeuse Star',
StartTime: new Date(2020, 1, 15, 10, 0),
EndTime: new Date(2018, 1, 15, 12, 30),
IsAllDay: false
},{
Id: 2,
Subject: 'Blue Moon Eclipse',
StartTime: new Date(2020, 1, 16, 12, 0),
EndTime: new Date(2018, 1, 16, 13, 0),
IsAllDay: false
}];
public selectedDate: Date = new Date(2020, 1, 15);
public eventSettings: EventSettingsModel = {
dataSource: this.data};
public timezoneDataSource : { Value: string, Text: string }[] = [
{ Value: 'Pacific/Niue', Text: 'Niue' },
{ Value: 'Pacific/Pago_Pago', Text: 'Pago Pago' },
{ Value: 'Pacific/Honolulu', Text: 'Hawaii Time' },
{ Value: 'Pacific/Rarotonga', Text: 'Rarotonga' },
{ Value: 'Pacific/Tahiti', Text: 'Tahiti' },
]
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Customizing the event editor using template
The event editor window can be customized using the editorTemplate
option. Create the custom window with required fields using a script template with type text/x-template.
Each field defined within template should contain the e-field class, so as to allow the processing of those field values internally. The ID of this customized script template section is assigned to the editorTemplate
option, so that these customized fields will be replaced onto the default editor window.
The e-field class is supported for the following Syncfusion components: DropDownList, DateTimePicker, MultiSelect, DatePicker, CheckBox, and TextBox. Since we have processed the field values internally for the above mentioned components.
As we are using our Syncfusion® sub-components within our editor using template in the following example, the custom defined form elements needs to be configured as required Syncfusion® components such as DropDownList and DateTimePicker within the popupOpen
event. This particular step can be skipped, if the user needs to simply use the usual form elements.
Learn how to customize the Angular Scheduler’s editor window with your own design in this video:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { DateTimePickerModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ElementRef, ViewChild } from '@angular/core';
import { extend, isNullOrUndefined } from '@syncfusion/ej2-base';
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { DateTimePicker } from '@syncfusion/ej2-calendars';
import { ChangeEventArgs } from '@syncfusion/ej2-calendars';
import { EventSettingsModel, PopupOpenEventArgs, ScheduleComponent } from '@syncfusion/ej2-angular-schedule';
import { eventData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule,
DropDownListModule,
DateTimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule #schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' [showQuickInfo]='showQuickInfo'>
<ng-template #editorTemplate let-data>
<table class="custom-event-editor" width="100%" cellpadding="5">
<tbody>
<tr>
<td class="e-textlabel">Summary</td>
<td colspan="4">
<input id="Subject" class="e-field e-input" type="text" value="" name="Subject" style="width: 100%" />
</td>
</tr>
<tr>
<td class="e-textlabel">Status</td>
<td colspan="4">
<ejs-dropdownlist id='EventType' class="e-field" data-name="EventType" placeholder='Choose Status'
[dataSource]='statusData' value="">
</ejs-dropdownlist>
</td>
</tr>
<tr>
<td class="e-textlabel">From</td>
<td colspan="4">
<ejs-datetimepicker id="StartTime" class="e-field" data-name="StartTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="startDateParser(data.startTime || data.StartTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">To</td>
<td colspan="4">
<ejs-datetimepicker id="EndTime" class="e-field" data-name="EndTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="endDateParser(data.endTime || data.EndTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">Reason</td>
<td colspan="4">
<textarea id="Description" class="e-field e-input" name="Description" rows="3" cols="50"
value="" style="width: 100%; height: 60px !important; resize: vertical"></textarea>
</td>
</tr>
</tbody>
</table>
</ng-template>
</ejs-schedule>`
})
export class AppComponent {
@ViewChild('schedule') public scheduleObj?: ScheduleComponent;
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfo: Boolean = false;
public startDate!: Date;
public endDate!: Date;
public eventSettings: EventSettingsModel = {
dataSource: eventData
};
public statusData: Object[] = ['New', 'Requested', 'Confirmed'];
public startDateParser(data: string) {
if (isNullOrUndefined(this.startDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.startDate)) {
return new Date(this.startDate);
}
return new Date();
}
public endDateParser(data: string) {
if (isNullOrUndefined(this.endDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.endDate)) {
return new Date(this.endDate);
}
return new Date();
}
public onDateChange(args: ChangeEventArgs): void {
if (!isNullOrUndefined(args.event as any)) {
if (args.element.id === "StartTime") {
this.startDate = args.value as Date;
} else if (args.element.id === "EndTime") {
this.endDate = args.value as Date;
}
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to customize header and footer using template
The editor window’s header and footer can be customized with templates using the editorHeaderTemplate
and editorFooterTemplate
options. Create a template script section for each, using text/x-template.
In this example, the header is customized to show the appointment’s subject via editorHeaderTemplate
, while editorFooterTemplate
is used to validate fields before saving or canceling the event.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import {CommonModule} from '@angular/common';
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import {
ScheduleComponent, MonthService, DayService, WeekService,
WorkWeekService, EventSettingsModel, PopupOpenEventArgs
} from '@syncfusion/ej2-angular-schedule';
@Component({
imports: [
ScheduleModule, CommonModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
encapsulation: ViewEncapsulation.None,
template: `
<ejs-schedule #schedule width='100%' height='550px' [eventSettings]='eventSettings' (popupOpen)="onPopupOpen($event)">
<ng-template #editorHeaderTemplate let-data>
<div *ngIf="data.Subject; else createNewEvent">
</div>
<ng-template #createNewEvent>
Create New Event
</ng-template>
</ng-template>
<ng-template #editorFooterTemplate>
<div id="verify">
<input type="checkbox" id="check-box" value="unchecked">
<label id="text">Verified</label>
</div>
<div id="right-button">
<button id="Save" class="e-control e-btn e-primary" disabled data-ripple="true">Save</button>
<button id="Cancel" class="e-control e-btn e-primary" data-ripple="true">Cancel</button>
</div>
</ng-template>
</ejs-schedule>`
})
export class AppComponent {
@ViewChild('schedule') public scheduleObj?: ScheduleComponent;
private today: Date = new Date();
private data: Record<string, any>[] = [{
Id: 1,
Subject: 'Surgery - Andrew',
StartTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 9, 0),
EndTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 10, 0),
IsAllDay: false
},
{
Id: 2,
Subject: 'Consulting - John',
StartTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 10, 0),
EndTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 11, 30),
IsAllDay: false
},
{
Id: 3,
Subject: 'Therapy - Robert',
StartTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 11, 30),
EndTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 12, 30),
IsAllDay: false
},
{
Id: 4,
Subject: 'Observation - Steven',
StartTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 12, 30),
EndTime: new Date(this.today.getFullYear(), this.today.getMonth(), this.today.getDate(), 13, 30),
IsAllDay: false
}];
public eventSettings: EventSettingsModel = { dataSource: this.data };
private onSaveButtonClick(args: PopupOpenEventArgs): void {
const data: Record<string, any> = {
Id: args.data?.['Id'],
Subject: (args.element.querySelector('#Subject') as HTMLInputElement).value,
StartTime: (args.element.querySelector('#StartTime') as any).ej2_instances[0].value,
EndTime: (args.element.querySelector('#EndTime') as any).ej2_instances[0].value,
IsAllDay: (args.element.querySelector('#IsAllDay')as HTMLInputElement).checked
};
if (args.target?.classList.contains('e-appointment')) {
this.scheduleObj?.saveEvent(data, 'Save');
} else {
data['Id'] = this.scheduleObj?.getEventMaxID();
this.scheduleObj?.addEvent(data);
}
this.scheduleObj?.closeEditor();
}
public onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'Editor') {
const saveButton: HTMLElement = args.element.querySelector('#Save') as HTMLElement;
const cancelButton: HTMLElement = args.element.querySelector('#Cancel') as HTMLElement;
const checkBox: HTMLInputElement = args.element.querySelector('#check-box') as HTMLInputElement;
checkBox.onchange = () => {
if (!(checkBox as HTMLInputElement).checked) {
saveButton.setAttribute('disabled', '');
} else {
saveButton.removeAttribute('disabled');
}
};
saveButton.onclick = () => {
this.onSaveButtonClick(args);
}
cancelButton.onclick = () => {
this.scheduleObj?.closeEditor();
};
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to add resource options within the editor template
Resource fields can be added to the editor template using a MultiSelect control to enable multiple resource selection.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { DateTimePickerModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component, ViewChild } from '@angular/core';
import { MultiSelect } from '@syncfusion/ej2-dropdowns';
import { DateTimePicker } from '@syncfusion/ej2-calendars';
import { ChangeEventArgs } from '@syncfusion/ej2-calendars';
import { isNullOrUndefined } from '@syncfusion/ej2-base'
import { ScheduleComponent, EventSettingsModel, DayService, WeekService, WorkWeekService, MonthService, PopupOpenEventArgs, GroupModel, AgendaService,
MonthAgendaService } from '@syncfusion/ej2-angular-schedule';
import { eventData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule,
DateTimePickerModule,
MultiSelectModule
],
standalone: true,
selector: 'app-root',
providers: [DayService, WeekService, WorkWeekService, MonthService, AgendaService,
MonthAgendaService],
// specifies the template string for the Schedule component
template: `<ejs-schedule #scheduleObj width='100%' height='550px' [selectedDate]='selectedDate' [views]='views'[eventSettings]='eventSettings' [showQuickInfo]='showQuickInfo' [group]='group'>
<e-resources>
<e-resource field="OwnerId" title="Owner" name="Owners"
[dataSource]="ownerDataSource"
textField="text" idField="id" colorField="color">
</e-resource>
</e-resources>
<ng-template #editorTemplate let-data>
<table class="custom-event-editor" width="100%" cellpadding="5">
<tbody>
<tr>
<td class="e-textlabel">Summary</td>
<td colspan="4">
<input id="Subject" class="e-field e-input" type="text" value="" name="Subject" style="width: 100%" />
</td>
</tr>
<tr>
<td class="e-textlabel">From</td>
<td colspan="4">
<ejs-datetimepicker id="StartTime" class="e-field" data-name="StartTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="startDateParser(data.startTime || data.StartTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">To</td>
<td colspan="4">
<ejs-datetimepicker id="EndTime" class="e-field" data-name="EndTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="endDateParser(data.endTime || data.EndTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">Owner</td>
<td colspan="4">
<ejs-multiselect id='OwnerId' [dataSource]='ownerDataSource' [fields]='fields' placeholder='Choose a owner' value=""></ejs-multiselect>
</td>
</tr>
<tr>
<td class="e-textlabel">Reason</td>
<td colspan="4">
<textarea id="Description" class="e-field e-input" name="Description" rows="3" cols="50" style="width: 100%; height: 60px !important; resize: vertical"></textarea>
</td>
</tr>
</tbody>
</table>
</ng-template>
</ejs-schedule>`
})
export class AppComponent {
@ViewChild('scheduleObj')
public scheduleObj?: ScheduleComponent;
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfo: Boolean = false;
public startDate!: Date;
public endDate!: Date;
public eventSettings: EventSettingsModel = {
dataSource: eventData
};
public group: GroupModel = { resources: ['Owners'] };
public ownerDataSource: Object[] = [
{ text: "Nancy", id: 1, color: "#1aaa55" },
{ text: "Smith", id: 2, color: "#7fa900" },
{ text: "Paul", id: 3, color: "#357cd2" }
];
public fields: Object = { text: 'text', value: 'id'}
public startDateParser(data: string) {
if (isNullOrUndefined(this.startDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.startDate)) {
return new Date(this.startDate);
}
return new Date();
}
public endDateParser(data: string) {
if (isNullOrUndefined(this.endDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.endDate)) {
return new Date(this.endDate);
}
return new Date();
}
public onDateChange(args: ChangeEventArgs): void {
if (!isNullOrUndefined(args.event as any)) {
if (args.element.id === "StartTime") {
this.startDate = args.value as Date;
} else if (args.element.id === "EndTime") {
this.endDate = args.value as Date;
}
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to add recurrence options within the editor template
The following code example shows how to add recurrence options within the editor template by importing RecurrenceEditor
.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule, RecurrenceEditorModule } from '@syncfusion/ej2-angular-schedule'
import { DateTimePickerModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ViewChild } from '@angular/core';
import { ChangeEventArgs } from '@syncfusion/ej2-calendars';
import { extend, isNullOrUndefined } from '@syncfusion/ej2-base';
import { DateTimePicker } from '@syncfusion/ej2-calendars';
import { EventSettingsModel, PopupOpenEventArgs, RecurrenceEditor, ScheduleComponent } from '@syncfusion/ej2-angular-schedule';
import { eventData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule,
RecurrenceEditorModule,
DateTimePickerModule
],
standalone: true,
selector: 'app-root',
providers: [DayService, WeekService, WorkWeekService, MonthService, AgendaService,
MonthAgendaService],
// specifies the template string for the Schedule component
template: `<ejs-schedule #scheduleObj width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' [showQuickInfo]='showQuickInfo' (popupOpen)='onPopupOpen($event)'>
<ng-template #editorTemplate let-data>
<table class="custom-event-editor" width="100%" cellpadding="5">
<tbody>
<tr>
<td class="e-textlabel">Summary</td>
<td colspan="4">
<input id="Subject" class="e-field e-input" type="text" value="" name="Subject" style="width: 100%" />
</td>
</tr>
<tr>
<td class="e-textlabel">From</td>
<td colspan="4">
<ejs-datetimepicker id="StartTime" class="e-field" data-name="StartTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="startDateParser(data.startTime || data.StartTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">To</td>
<td colspan="4">
<ejs-datetimepicker id="EndTime" class="e-field" data-name="EndTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="endDateParser(data.endTime || data.EndTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td colspan="4">
<ejs-recurrenceeditor #recurrenceObj></ejs-recurrenceeditor>
</td>
</tr>
<tr>
<td class="e-textlabel">Reason</td>
<td colspan="4">
<textarea id="Description" class="e-field e-input" name="Description" rows="3" cols="50" style="width: 100%; height: 60px !important; resize: vertical"></textarea>
</td>
</tr>
</tbody>
</table>
</ng-template>
</ejs-schedule>`
})
export class AppComponent {
@ViewChild('scheduleObj')
public scheduleObj?: ScheduleComponent;
@ViewChild('recurrenceObj') recurrObject!: RecurrenceEditor;
public selectedDate: Date = new Date(2018, 1, 15);
public startDate!: Date;
public endDate!: Date;
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfo: Boolean = false;
public eventSettings: EventSettingsModel = {
dataSource: eventData
};
public startDateParser(data: string) {
if (isNullOrUndefined(this.startDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.startDate)) {
return new Date(this.startDate);
}
return new Date();
}
public endDateParser(data: string) {
if (isNullOrUndefined(this.endDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.endDate)) {
return new Date(this.endDate);
}
return new Date();
}
public onDateChange(args: ChangeEventArgs): void {
if (!isNullOrUndefined(args.event as any)) {
if (args.element.id === "StartTime") {
this.startDate = args.value as Date;
} else if (args.element.id === "EndTime") {
this.endDate = args.value as Date;
}
}
}
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'Editor') {
if (!this.recurrObject.element.classList.contains('e-recurrenceeditor')) {
(this.scheduleObj!.eventWindow as any).recurrenceEditor = this.recurrObject;
}
(this.recurrObject.element)!.style.display = (this.scheduleObj!.currentAction == "EditOccurrence") ? 'none' : 'block';
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Applying validation to editor template fields
The following code example demonstrates how to apply validation rules to the status field in a custom event editor.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { DateTimePickerModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { Component} from '@angular/core';
import { DateTimePicker } from '@syncfusion/ej2-calendars';
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { FormValidator } from '@syncfusion/ej2-inputs';
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { ChangeEventArgs } from '@syncfusion/ej2-calendars';
import { EventSettingsModel, DayService, WeekService, WorkWeekService, MonthService, AgendaService,
MonthAgendaService, PopupOpenEventArgs, EJ2Instance } from '@syncfusion/ej2-angular-schedule';
import { eventData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule,
DropDownListModule,
DateTimePickerModule
],
standalone: true,
selector: 'app-root',
providers: [DayService, WeekService, WorkWeekService, MonthService, AgendaService,
MonthAgendaService],
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' [showQuickInfo]='showQuickInfo' (popupOpen)='onPopupOpen($event)'>
<ng-template #editorTemplate let-data>
<table class="custom-event-editor" width="100%" cellpadding="5">
<tbody>
<tr>
<td class="e-textlabel">Summary</td>
<td colspan="4">
<input id="Subject" class="e-field e-input" type="text" value="" name="Subject" style="width: 100%" />
</td>
</tr>
<tr>
<td class="e-textlabel">Status</td>
<td colspan="4">
<ejs-dropdownlist id='EventType' class="e-field" data-name="EventType" placeholder='Choose Status'
[dataSource]='statusData' value="" (select)="eventSelect($event)">
</ejs-dropdownlist>
</td>
</tr>
<tr>
<td class="e-textlabel">From</td>
<td colspan="4">
<ejs-datetimepicker id="StartTime" class="e-field" data-name="StartTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="startDateParser(data.startTime || data.StartTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">To</td>
<td colspan="4">
<ejs-datetimepicker id="EndTime" class="e-field" data-name="EndTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="endDateParser(data.endTime || data.EndTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">Reason</td>
<td colspan="4">
<textarea id="Description" class="e-field e-input" name="Description" rows="3" cols="50"
style="width: 100%; height: 60px !important; resize: vertical"></textarea>
</td>
</tr>
</tbody>
</table>
</ng-template>
</ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfo: Boolean = false;
public startDate!: Date;
public endDate!: Date;
public statusData: Object[] = ['New', 'Requested', 'Confirmed'];
public eventSettings: EventSettingsModel = {
dataSource: eventData
};
public eventSelect(args: any) {
if (!isNullOrUndefined(document.getElementById("EventType_Error")as any)) {
document.getElementById("EventType_Error")!.style.display = "none";
}
}
public startDateParser(data: string) {
if (isNullOrUndefined(this.startDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.startDate)) {
return new Date(this.startDate);
}
return new Date();
}
public endDateParser(data: string) {
if (isNullOrUndefined(this.endDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.endDate)) {
return new Date(this.endDate);
}
return new Date();
}
public onDateChange(args: ChangeEventArgs): void {
if (!isNullOrUndefined(args.event as any)) {
if (args.element.id === "StartTime") {
this.startDate = args.value as Date;
} else if (args.element.id === "EndTime") {
this.endDate = args.value as Date;
}
}
}
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'Editor') {
if (!isNullOrUndefined(document.getElementById("EventType_Error")as any)) {
document.getElementById("EventType_Error")!.style.display = "none";
document.getElementById("EventType_Error")!.style.left = "351px";
}
let formElement: HTMLElement = <HTMLElement>args.element.querySelector('.e-schedule-form');
let validator: FormValidator = ((formElement as EJ2Instance).ej2_instances[0] as FormValidator);
validator.addRules('EventType', { required: true });
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to save the customized event editor using a template
If the e-field class is not added to template fields, set field values manually in the popupClose
event.
Note: Data can be retrieved only on the save
and delete
options, not on close
or cancel
.
The following example shows how to handle saving event data by handling the popupClose
event.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { RatingModule } from '@syncfusion/ej2-angular-inputs'
import { DateTimePickerModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { Component, ViewChild, ElementRef } from '@angular/core';
import { DropDownList } from '@syncfusion/ej2-dropdowns';
import { DateTimePicker } from '@syncfusion/ej2-calendars';
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { ChangeEventArgs } from '@syncfusion/ej2-calendars';
import { RatingComponent } from '@syncfusion/ej2-angular-inputs';
import { EventSettingsModel, DayService, WeekService, WorkWeekService, MonthService, PopupOpenEventArgs, PopupCloseEventArgs,AgendaService, MonthAgendaService } from '@syncfusion/ej2-angular-schedule';
import { eventData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule,
DropDownListModule,
DateTimePickerModule,
RatingModule
],
standalone: true,
selector: 'app-root',
providers: [DayService, WeekService, WorkWeekService, MonthService, AgendaService,
MonthAgendaService],
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' [showQuickInfo]='showQuickInfo' (popupOpen)='onPopupOpen($event)' (popupClose) ='onPopupClose($event)'>
<ng-template #editorTemplate let-data>
<table class="custom-event-editor" width="100%" cellpadding="5">
<tbody>
<tr>
<td class="e-textlabel">Summary</td>
<td colspan="4">
<input id="Subject" class="e-input" type="text" name="Subject" style="width: 100%" #subject value=""/>
</td>
</tr>
<tr>
<td class="e-textlabel">Rating</td>
<td colspan="4">
<input ejs-rating id='rating1' #rating value=""/>
</td>
</tr>
<tr>
<td class="e-textlabel">From</td>
<td colspan="4">
<ejs-datetimepicker id="StartTime" class="e-field" data-name="StartTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="startDateParser(data.startTime || data.StartTime)" #startTime>
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">To</td>
<td colspan="4">
<ejs-datetimepicker id="EndTime" class="e-field" data-name="EndTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="endDateParser(data.endTime || data.EndTime)" #endTime>
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">Reason</td>
<td colspan="4">
<textarea id="Description" class="e-input" name="Description" rows="3" cols="50" style="width: 100%;
height: 60px !important; resize: vertical" #textArea value="" ></textarea>
</td>
</tr>
</tbody>
</table>
</ng-template>
</ejs-schedule>`
})
export class AppComponent {
@ViewChild('rating') public rating!: RatingComponent;
@ViewChild('startTime') public startTime!: DateTimePicker;
@ViewChild('endTime') public endTime!: DateTimePicker;
@ViewChild('textArea') public textArea!: ElementRef<HTMLInputElement>;
@ViewChild('subject') public subject!: ElementRef<HTMLInputElement>;
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfo: Boolean = false;
public startDate!: Date;
public endDate!: Date;
public eventSettings: EventSettingsModel = {
dataSource: eventData
};
public statusData: Object[] = ['New', 'Requested', 'Confirmed'];
onPopupOpen(args: PopupOpenEventArgs) : void {
if (args.type === 'Editor') {
if (this.subject.nativeElement) {
(this.subject.nativeElement as HTMLInputElement).value = ((<{ [key: string]: Object; }>(args.data))['Subject'] as string) || "";
}
if (this.textArea.nativeElement) {
(this.textArea.nativeElement as HTMLInputElement).value = (<{ [key: string]: Object; }>(args.data))['Description'] as string || "";
}
}
}
onPopupClose(args: PopupCloseEventArgs) : void {
if (args.type === 'Editor' && !isNullOrUndefined((args as any).data)) {
if ( this.subject.nativeElement ) {
(<{ [key: string]: Object; }>(args.data))['Subject'] = (this.subject.nativeElement as HTMLInputElement).value;
}
if(this.rating.element) {
((<{ [key: string]: Object; }>(args.data))['Rating'] as string) = (this.rating.element as HTMLInputElement).value;
}
if (this.startTime.element) {
(<{ [key: string]: Object; }>(args.data))['StartTime'] = (this.startTime.element as HTMLInputElement).value;
}
if (this.endTime.element) {
(<{ [key: string]: Object; }>(args.data))['EndTime'] = (this.endTime.element as HTMLInputElement).value;
}
if (this.textArea.nativeElement) {
((<{ [key: string]: Object; }>(args.data))['Description'] as string) = (this.textArea.nativeElement as HTMLInputElement).value;
}
}
}
public startDateParser(data: string) {
if (isNullOrUndefined(this.startDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.startDate)) {
return new Date(this.startDate);
}
return new Date();
}
public endDateParser(data: string) {
if (isNullOrUndefined(this.endDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.endDate)) {
return new Date(this.endDate);
}
return new Date();
}
public onDateChange(args: ChangeEventArgs): void {
if (!isNullOrUndefined(args.event as any)) {
if (args.element.id === "StartTime") {
this.startDate = args.value as Date;
} else if (args.element.id === "EndTime") {
this.endDate = args.value as Date;
}
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
To prevent only specific popups within the popupClose
event, check the popup type. Types include:
Type | Description |
---|---|
Editor | For Detailed editor window. |
QuickInfo | For Quick popup which opens on cell click. |
EditEventInfo | For Quick popup which opens on event click. |
ViewEventInfo | For Quick popup which opens on responsive mode. |
EventContainer | For more event indicator popup. |
RecurrenceAlert | For edit recurrence event alert popup. |
DeleteAlert | For delete confirmation popup. |
ValidationAlert | For validation alert popup. |
RecurrenceValidationAlert | For recurrence validation alert popup. |
How to enable save button in customized event editor using template
Initially, the e-custom-disable class is added to the Save button. Once all required fields are filled, the class is removed, enabling the button.
The code sample below enables the Save button in a custom event editor by handling keyup
and change
events.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { DropDownListModule } from '@syncfusion/ej2-angular-dropdowns'
import { DateTimePickerModule, TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { Component, ViewEncapsulation, ViewChild } from "@angular/core";
import { extend, isNullOrUndefined } from "@syncfusion/ej2-base";
import { ChangeEventArgs } from '@syncfusion/ej2-calendars';
import { DropDownList } from "@syncfusion/ej2-dropdowns";
import { DateTimePicker } from "@syncfusion/ej2-calendars";
import { FormValidators, FormValidator, TextBox } from "@syncfusion/ej2-angular-inputs";
import { PopupOpenEventArgs, EventRenderedArgs, ScheduleComponent, MonthService, DayService, WeekService,
WorkWeekService, EventSettingsModel, ResizeService, DragAndDropService, EJ2Instance , AgendaService, MonthAgendaService
} from "@syncfusion/ej2-angular-schedule";
import { eventData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule,
DropDownListModule,
DateTimePickerModule
],
standalone: true,
selector: 'app-root',
providers: [ MonthService, DayService, WeekService, WorkWeekService, ResizeService, DragAndDropService, MonthAgendaService, AgendaService],
encapsulation: ViewEncapsulation.None,
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' [showQuickInfo]='showQuickInfo' (popupOpen)='onPopupOpen($event)' >
<ng-template #editorTemplate let-data>
<table class="custom-event-editor" width="100%" cellpadding="5">
<tbody>
<tr>
<td class="e-textlabel">Summary</td>
<td colspan="4">
<input id="Subject" class=" e-field e-input" type="text" name="Subject" style="width: 100%" value="" (keyup)="onChange($event)"/>
</td>
</tr>
<tr>
<td class="e-textlabel">Status</td>
<td colspan="4">
<ejs-dropdownlist id='EventType' class="e-field" data-name="EventType" placeholder='Choose Status'
[dataSource]='statusData' value="">
</ejs-dropdownlist>
</td>
</tr>
<tr>
<td class="e-textlabel">From</td>
<td colspan="4">
<ejs-datetimepicker id="StartTime" class="e-field" data-name="StartTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="startDateParser(data.startTime || data.StartTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">To</td>
<td colspan="4">
<ejs-datetimepicker id="EndTime" class="e-field" data-name="EndTime" format="M/dd/yy h:mm a"
(change)="onDateChange($event)" [value]="endDateParser(data.endTime || data.EndTime)">
</ejs-datetimepicker>
</td>
</tr>
<tr>
<td class="e-textlabel">Reason</td>
<td colspan="4">
<textarea id="Description" class="e-field e-input" name="Description" rows="3" cols="50" style="width: 100%;
height: 60px !important; resize: vertical" value="" (keyup)="onChange($event)"></textarea>
</td>
</tr>
</tbody>
</table>
</ng-template>
</ejs-schedule>`
})
export class AppComponent {
@ViewChild("scheduleObj") scheduleObj: ScheduleComponent | undefined;
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfo: Boolean = false;
public startDate!: Date;
public endDate!: Date;
public eventSettings: EventSettingsModel = {
dataSource: eventData,
fields: {
subject: { name: "Subject", validation: { required: true } },
description: {
name: "Description",
validation: { required: true }
}
}
};
public validator?: FormValidator;
public statusFields: Object = { text: "StatusText", value: "StatusText" };
public StatusData: Object[] = [
{ StatusText: "New", Id: 1 },
{ StatusText: "Requested", Id: 2 },
{ StatusText: "Confirmed", Id: 3 }
];
public onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === "Editor") {
const formElement: HTMLElement = args.element.querySelector(".e-schedule-form") as HTMLElement;
this.validator = (formElement as EJ2Instance).ej2_instances[0] as FormValidator;
this.validator.addRules("EventType", { required: [true, "This field is required."]});
if (args.target!.classList.contains("e-work-cells")) {
args.element.querySelector(".e-event-save")!.classList.add("e-custom-disable");
}
}
}
public onChange(args : any) {
let form = (document.querySelector(".e-schedule-form") as any).ej2_instances[0];
if (args.element && !args.e) {
return;
}
let names = ["Subject", "Description", "EventType"];
names.forEach(e => {
form.validateRules(e);
});
let isValidated = false;
let errorElements = document.querySelector(".e-dlg-content")!.querySelectorAll(".e-schedule-error");
for (let i = 0; i < errorElements.length; i++) {
isValidated =(errorElements[i] as any).style.display === "none" ? true : false;
if (isValidated === false) {
break;
}
}
let saveBtn = document.querySelector(".e-custom-disable");
if (isValidated && saveBtn) {
saveBtn.classList.remove("e-custom-disable");
} else if (!isValidated && !saveBtn) {
document.querySelector(".e-event-save")!.classList.add("e-custom-disable");
}
}
public statusData: Object[] = ['New', 'Requested', 'Confirmed'];
public startDateParser(data: string) {
if (isNullOrUndefined(this.startDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.startDate)) {
return new Date(this.startDate);
}
return new Date();
}
public endDateParser(data: string) {
if (isNullOrUndefined(this.endDate) && !isNullOrUndefined(data)) {
return new Date(data);
} else if (!isNullOrUndefined(this.endDate)) {
return new Date(this.endDate);
}
return new Date();
}
public onDateChange(args: ChangeEventArgs): void {
if (!isNullOrUndefined(args.event as any)) {
if (args.element.id === "StartTime") {
this.startDate = args.value as Date;
} else if (args.element.id === "EndTime") {
this.endDate = args.value as Date;
}
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Quick popups
The quick info popups are the ones that gets opened, when a cell or appointment is single clicked on the desktop mode. On single clicking a cell, you can simply provide a subject and save it. Also, while single clicking on an event, a popup will be displayed where you can get the overview of the event information. You can also edit or delete those events through the options available in it.
By default, popups are displayed over cells and appointments. To disable, set showQuickInfo
to false
.
The quick popup that opens while single clicking on the cells are not applicable on mobile devices.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel} from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [eventSettings]='eventSettings' [showQuickInfo]='showQuickInfo'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfo: Boolean = false;
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to open QuickInfo popup on multiple cell selection
By default the QuickInfo
popup will open on single click of the cell. To open the quick info popup on multiple cell selection, you need to select the cells and press enter
key. You can open this popup immediately after multiple cell selection by setting up true
to quickInfoOnSelectionEnd
property where as its default value is false
.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [views]='views' [quickInfoOnSelectionEnd]='showQuickInfoOnSelectionEnd'></ejs-schedule>`
})
export class AppComponent {
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public showQuickInfoOnSelectionEnd: Boolean = true;
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to change the watermark text of quick popup subject
By default, Add Title
text is displayed on the subject field of quick popup. To change the default watermark text, change the value of the appropriate localized word collection used in the Scheduler.
L10n.load({
'en-US': {
'schedule': {
'addTitle' : 'New Title'
}
}
});
Customizing quick popups
The look and feel of the built-in quick popup window, which opens when single clicked on the cells or appointments can be customized by making use of the quickInfoTemplates
property of the Scheduler. There are 3 sub-options available to customize them easily,
- header - Accepts the template design that customizes the header part of the quick popup.
- content - Accepts the template design that customizes the content part of the quick popup.
- footer - Accepts the template design that customizes the footer part of the quick popup.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { CommonModule } from '@angular/common';
import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { ScheduleComponent, CurrentAction, EventSettingsModel, DayService, WeekService, WorkWeekService, MonthService, PopupOpenEventArgs, AgendaService,
MonthAgendaService } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule, CommonModule
],
standalone: true,
selector: 'app-root',
providers: [DayService, WeekService, WorkWeekService, MonthService, AgendaService,
MonthAgendaService],
// specifies the template string for the Schedule component
template: `<ejs-schedule #scheduleObj width='100%' height='550px' [selectedDate]="selectedDate" [eventSettings]="eventSettings"
(popupOpen)="onPopupOpen($event)">
<!-- Header template -->
<ng-template #quickInfoTemplatesHeader let-data>
<div *ngIf="data.elementType == 'cell' || data.elementType == 'event'">
<div class="e-popup-header">
<div class="e-header-icon-wrapper">
<div *ngIf="data.elementType == 'event'" class="subject"></div>
<button class="e-close e-close-icon e-icons" title="Close" (click)="onCloseClick()"></button>
</div>
</div>
</div>
</ng-template>
<!-- Content Template -->
<ng-template #quickInfoTemplatesContent let-data>
<div *ngIf="data.elementType == 'cell'" class="e-cell-content">
<form class="e-schedule-form">
<div style="padding:10px">
<input class="subject e-field e-input" type="text" name="Subject" placeholder="Title" style="width:100%">
</div>
<div style="padding:10px">
<input class="location e-field e-input" type="text" name="Location" placeholder="Location" style="width:100%">
</div>
</form>
</div>
<div *ngIf="data.elementType == 'event'" class="e-event-content">
<div class="start-time">Start: </div>
<div class="end-time">End: </div>
<div *ngIf="data.Location != undefined && data.Location != ''" class="location">Location: </div>
</div>
</ng-template>
<!-- Footer Template -->
<ng-template #quickInfoTemplatesFooter let-data>
<div *ngIf="data.elementType == 'cell'" class="e-cell-footer">
<div class="left-button">
<button class="e-event-details" title="Extra Details" (click)="onDetailsClick($event)">More Details</button>
</div>
<div class="right-button">
<button class="e-event-create" title="Add" (click)="onAddClick($event)">Add</button>
</div>
</div>
<div *ngIf="data.elementType == 'event'" class="e-event-footer">
<div class="left-button">
<button class="e-delete" title="Delete" (click)="onDeleteClick($event)">Delete</button>
<button *ngIf="data.RecurrenceRule != undefined && data.RecurrenceRule != ''" class="e-delete-series"
title="Delete" (click)="onDeleteClick($event)">Delete Series</button>
</div>
<div class="right-button">
<button class="e-edit" title="Edit" (click)="onEditClick($event)">Edit</button>
<button *ngIf="data.RecurrenceRule != undefined && data.RecurrenceRule != ''" class="e-edit-series"
title="Edit" (click)="onEditClick($event)">Edit Series</button>
</div>
</div>
</ng-template>
</ejs-schedule>`,
styleUrls: ['./index.css'],
encapsulation: ViewEncapsulation.None,
})
export class AppComponent {
@ViewChild('scheduleObj')
public scheduleObj?: ScheduleComponent;
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
public selectedDate: Date = new Date(2018, 1, 15);
private selectionTarget: Element | undefined;
public onPopupOpen(args: PopupOpenEventArgs): void {
this.selectionTarget = undefined;
this.selectionTarget = args.target;
}
public onDetailsClick(Data: any): void {
this.onCloseClick();
const data: Object = this.scheduleObj?.getCellDetails(this.scheduleObj.getSelectedElements()) as Object;
this.scheduleObj?.openEditor(data, 'Add');
}
public onAddClick(Data: any): void {
this.onCloseClick();
const data: Object = this.scheduleObj?.getCellDetails(this.scheduleObj.getSelectedElements()) as Object;
const eventData: { [key: string]: Object } | undefined= this.scheduleObj?.eventWindow.getObjectFromFormData('e-quick-popup-wrapper');
this.scheduleObj?.eventWindow.convertToEventData(data as { [key: string]: Object }, eventData as any);
(eventData as any)['Id'] = this.scheduleObj?.eventBase.getEventMaxID() as number + 1;
this.scheduleObj?.addEvent(eventData as any);
}
public onEditClick(args: any): void {
if (this.selectionTarget) {
let eventData: { [key: string]: Object } = this.scheduleObj?.getEventDetails(this.selectionTarget) as { [key: string]: Object };
let currentAction: CurrentAction = 'Save';
if (!isNullOrUndefined(eventData['RecurrenceRule']) && eventData['RecurrenceRule'] !== '') {
if (args.target.classList.contains('e-edit-series')) {
currentAction = 'EditSeries';
eventData = this.scheduleObj?.eventBase.getParentEvent(eventData, true) as any;
} else {
currentAction = 'EditOccurrence';
}
}
this.scheduleObj?.openEditor(eventData, currentAction);
}
}
public onDeleteClick(args: any): void {
this.onCloseClick();
if (this.selectionTarget) {
const eventData: { [key: string]: Object } = this.scheduleObj?.getEventDetails(this.selectionTarget) as { [key: string]: Object };
let currentAction: CurrentAction = 'Delete';
if (!isNullOrUndefined(eventData['RecurrenceRule']) && eventData['RecurrenceRule'] !== '') {
currentAction = args.target.classList.contains('e-delete-series') ? 'DeleteSeries' : 'DeleteOccurrence';
}
this.scheduleObj?.deleteEvent(eventData, currentAction);
}
}
public onCloseClick(): void {
this.scheduleObj?.quickPopup.quickPopupHide();
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Quick popups in adaptive mode can also be customized using
quickInfoTemplates
and thee-device
class.
More events indicator and popup
When the number of appointments count that lies on a particular time range * default appointment height exceeds the default height of a cell in month view and all other timeline views, a + more
text indicator will be displayed at the bottom of those cells. This indicator denotes that the cell contains few more appointments in it and clicking on that will display a popup displaying all the appointments present on that day.
To disable this option of showing popup with all hidden appointments, while clicking on the text indicator, you can do code customization within the
popupOpen
event.
The same indicator is displayed on all-day row in calendar views such as day, week and work week views alone, when the number of appointment count present in a cell exceeds three. Clicking on the text indicator here will not open a popup, but will allow the expand/collapse option for viewing the remaining appointments present in the all-day row.
The following code example shows how to disable the display of such popups while clicking on the more text indicator.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel, PopupOpenEventArgs } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [currentView]='currentView' [eventSettings]='eventSettings' (popupOpen)='onPopupOpen($event)'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public currentView: string = 'Month';
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'EventContainer') {
args.cancel = true;
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to customize the popup that opens on more indicator
The following code example shows you how to customize the default more indicator popup in which number of events rendered count on the day has been shown in the header.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ViewEncapsulation } from '@angular/core';
import { Internationalization } from '@syncfusion/ej2-base';
import { EventSettingsModel, PopupOpenEventArgs } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [currentView]='currentView' [cssClass]='cssClass' [eventSettings]='eventSettings' (popupOpen)='onPopupOpen($event)'></ejs-schedule>`,
styleUrls: ['./index.css'],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public currentView: string = 'Month';
public cssClass: string = 'schedule-more-indicator';
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'EventContainer') {
let instance: Internationalization = new Internationalization();
let date: string = instance.formatDate((<any>args.data).date, { skeleton: 'MMMEd' });
((args.element.querySelector('.e-header-date')) as HTMLElement).innerText = date;
((args.element.querySelector('.e-header-day')) as HTMLElement).innerText = 'Event count: ' + (<any>args.data).event.length;
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to customize the appointments rendered on more indicator popup
The following code example shows you how to customize the details shown on the appointments rendered on more indicator popup.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { Internationalization, createElement } from '@syncfusion/ej2-base';
import { EventSettingsModel,PopupOpenEventArgs, ScheduleComponent } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule #scheduleObj width='100%' height='650px' cssClass="more-indicator-app" [selectedDate]="selectedDate" [views]="views" [eventSettings]="eventSettings" (popupOpen)="onPopupOpen($event)">
</ejs-schedule>`,
styles: [`.more-indicator-app .e-more-popup-wrapper .e-appointment {
display: inline-grid;
height: 60px;
}
.more-indicator-app .e-more-popup-wrapper .e-appointment .e-subject {
white-space: initial;
}`],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild('scheduleObj') public scheduleObj?: ScheduleComponent;
public selectedDate: Date = new Date(2018, 1, 1);
public views: Array<string> = ['Month'];
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
private instance: Internationalization = new Internationalization();
getTimeString(value: Date): string {
return this.instance.formatDate(value, { format: 'hh:mm:a : dd-MMM-y' });
}
onPopupOpen(args: PopupOpenEventArgs): void {
if (args.type === 'EventContainer') {
let appointments = args.element.querySelectorAll('.e-appointment');
for (let i = 0; i < appointments.length; i++) {
let eventData = this.scheduleObj?.getEventDetails(appointments[i]) as { [key: string]: Object };
let time = this.getTimeString(eventData['StartTime'] as Date) + ' - ' + this.getTimeString(eventData['EndTime'] as Date);
let customElement = createElement('div', { className: 'e-more-popup-event-time' });
customElement.innerText = time;
appointments[i].insertBefore(customElement, appointments[i].firstChild);
}
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to prevent the display of popup when clicking on the more text indicator
To prevent the popup window from appearing, set the cancel
property to true
in the MoreEventsClick
event.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel, MoreEventsClickArgs } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [currentView]='currentView' [eventSettings]='eventSettings' (moreEventsClick)='onMoreEventsClick($event)'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public currentView: string = 'Month';
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
onMoreEventsClick(args: MoreEventsClickArgs): void {
args.cancel = true;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to navigate Day view when clicking on more text indicator
The following code example shows you how to customize the MoreEventsClick
property to navigate to the Day view when clicking on the more text indicator.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component } from '@angular/core';
import { EventSettingsModel, MoreEventsClickArgs } from '@syncfusion/ej2-angular-schedule';
import { scheduleData } from './datasource';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<ejs-schedule width='100%' height='550px' [selectedDate]='selectedDate' [views]='views' [currentView]='currentView' [eventSettings]='eventSettings' (moreEventsClick)='onMoreEventsClick($event)'></ejs-schedule>`
})
export class AppComponent {
public selectedDate: Date = new Date(2018, 1, 15);
public views: Array<string> = ['Day', 'Week', 'WorkWeek', 'Month'];
public currentView: string = 'Month';
public eventSettings: EventSettingsModel = {
dataSource: scheduleData
};
onMoreEventsClick(args: MoreEventsClickArgs): void {
args.isPopupOpen = false;
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to close the editor window manually
You can close the editor window by using closeEditor method.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { ButtonComponent } from '@syncfusion/ej2-angular-buttons';
import { EventSettingsModel, ScheduleComponent } from '@syncfusion/ej2-angular-schedule';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<button ejs-button cssClass= 'e-custom-close' (click)='closeEditor()'> closeEditor </button> <ejs-schedule #scheduleObj width='100%' height='650px' cssClass="more-indicator-app" [selectedDate]="selectedDate" [views]="views" [eventSettings]="eventSettings"></ejs-schedule>`,
})
export class AppComponent {
@ViewChild('scheduleObj') public scheduleObj?: ScheduleComponent;
public selectedDate: Date = new Date(2023, 2, 5);
public views: Array<string> = ['Month'];
public eventSettings: EventSettingsModel = {
dataSource: [{
Id: 1,
Subject: 'Review Meeting',
StartTime: new Date(2023, 2, 5, 20, 0, 0),
EndTime: new Date(2023, 2, 5, 21, 0, 0)
}]
};
closeEditor(): void {
this.scheduleObj?.closeEditor();
};
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to open the quick info popup manually
You can open the quick info popup in scheduler by using the openQuickInfoPopup public method. To open the cell quick info popup, you can pass the cell data as an argument to the method. To open the event quick info popup, you should pass the event data object as an argument to the method.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ViewChild } from '@angular/core';
import { EventSettingsModel, ScheduleComponent} from '@syncfusion/ej2-angular-schedule';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<button ejs-button cssClass= 'e-custom-close' (click)='cellClick()'> Show Cell Click Popup </button>
<button ejs-button cssClass= 'e-custom-close' (click)='eventClick()'> Show Event Click Popup </button>
<ejs-schedule #scheduleObj width='100%' height='550px' [selectedDate]="selectedDate" [eventSettings]="eventSettings" > <e-views> <e-view option="Week"></e-view> <e-view option="WorkWeek"></e-view> <e-view option="Month"></e-view> <e-view option="Day"></e-view> </e-views> </ejs-schedule>`
})
export class AppComponent {
@ViewChild('scheduleObj')
public scheduleObj?: ScheduleComponent;
public selectedDate: Date = new Date(2023, 2, 5);
public eventSettings: EventSettingsModel = {
dataSource: [{
Id: 1,
Subject: 'Review Meeting',
StartTime: new Date(2023, 2, 5, 9, 0, 0),
EndTime: new Date(2023, 2, 5, 10, 0, 0)
}]
};
cellClick(): void {
let cellData: Object = {
Subject: 'Review Meeting',
StartTime: new Date(2023, 2, 5, 9, 0, 0),
EndTime: new Date(2023, 2, 5, 10, 0, 0)
};
this.scheduleObj?.openQuickInfoPopup(cellData);
}
eventClick(): void {
let eventData: Object = {
Id: 1,
Subject: 'Review Meeting',
StartTime: new Date(2023, 2, 5, 9, 0, 0),
EndTime: new Date(2023, 2, 5, 10, 0, 0)
};
this.scheduleObj?.openQuickInfoPopup(eventData);
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
How to close the quick info popup manually
You can close the quick info popup in scheduler by using the closeQuickInfoPopup public method. The following code example demonstrates the how to close quick info popup manually.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { ScheduleModule } from '@syncfusion/ej2-angular-schedule'
import { TimePickerModule } from '@syncfusion/ej2-angular-calendars'
import { DayService, WeekService, WorkWeekService, MonthService, AgendaService, MonthAgendaService} from '@syncfusion/ej2-angular-schedule'
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { ButtonComponent } from '@syncfusion/ej2-angular-buttons';
import { EventSettingsModel, ScheduleComponent } from '@syncfusion/ej2-angular-schedule';
@Component({
imports: [
ScheduleModule,
TimePickerModule
],
providers: [DayService,
WeekService,
WorkWeekService,
MonthService,
AgendaService,
MonthAgendaService],
standalone: true,
selector: 'app-root',
// specifies the template string for the Schedule component
template: `<button ejs-button cssClass= 'e-custom-close' (click)="CloseQuickInfoPopup">CloseQuickInfoPopup</button> <ejs-schedule #scheduleObj width='100%' height='650px' cssClass="more-indicator-app" [selectedDate]="selectedDate" [views]="views" [eventSettings]="eventSettings"></ejs-schedule>`,
})
export class AppComponent {
@ViewChild('scheduleObj') public scheduleObj?: ScheduleComponent;
public selectedDate: Date = new Date(2023, 2, 5);
public views: Array<string> = ['Month'];
public eventSettings: EventSettingsModel = {
dataSource: [{
Id: 1,
Subject: 'Review Meeting',
StartTime: new Date(2023, 2, 5, 20, 0, 0),
EndTime: new Date(2023, 2, 5, 21, 0, 0)
}]
};
CloseQuickInfoPopup(): void {
this.scheduleObj?.closeQuickInfoPopup();
};
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
You can refer to our Angular Scheduler feature tour page for its groundbreaking feature representations. You can also explore our Angular Scheduler example to knows how to present and manipulate data.