Show quick info template in React Schedule component
28 Jul 202324 minutes to read
This demo showcases the quick popups for cells and appointments with the customized templates.
import { useRef } from 'react';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ScheduleComponent, ResourcesDirective, ResourceDirective, Day, Week, WorkWeek, Month, Agenda, MonthAgenda, Inject } from '@syncfusion/ej2-react-schedule';
import { Internationalization } from '@syncfusion/ej2-base';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { TextBoxComponent } from '@syncfusion/ej2-react-inputs';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { ScheduleData } from './datasource';
const App = () => {
const eventTypeObj = useRef(null);
const titleObj = useRef(null);
const notesObj = useRef(null);
const scheduleObj = useRef(null);
const intl = new Internationalization();
const roomData = [
{ Name: 'Jammy', Id: 1, Capacity: 20, Color: '#ea7a57', Type: 'Conference' },
{ Name: 'Tweety', Id: 2, Capacity: 7, Color: '#7fa900', Type: 'Cabin' },
{ Name: 'Nestle', Id: 3, Capacity: 5, Color: '#5978ee', Type: 'Cabin' },
{ Name: 'Phoenix', Id: 4, Capacity: 15, Color: '#fec200', Type: 'Conference' },
{ Name: 'Mission', Id: 5, Capacity: 25, Color: '#df5286', Type: 'Conference' },
{ Name: 'Hangout', Id: 6, Capacity: 10, Color: '#00bdae', Type: 'Cabin' },
{ Name: 'Rick Roll', Id: 7, Capacity: 20, Color: '#865fcf', Type: 'Conference' },
{ Name: 'Rainbow', Id: 8, Capacity: 8, Color: '#1aaa55', Type: 'Cabin' },
{ Name: 'Swarm', Id: 9, Capacity: 30, Color: '#df5286', Type: 'Conference' },
{ Name: 'Photogenic', Id: 10, Capacity: 25, Color: '#710193', Type: 'Conference' }
];
const eventSettings = { dataSource: ScheduleData };
const headerTemplate = (props) => {
return (<div className="quick-info-header">
<div className="quick-info-header-content" style={getHeaderStyles(props)}>
<div className="quick-info-title">{getHeaderTitle(props)}</div>
<div className="duration-text">{getHeaderDetails(props)}</div>
</div>
</div>);
}
const contentTemplate = (props) => {
return (<div className="quick-info-content">
{props.elementType === 'cell' ?
<div className="e-cell-content">
<div className="content-area">
<TextBoxComponent id="title" ref={titleObj} placeholder="Title" />
</div>
<div className="content-area">
<DropDownListComponent id="eventType" ref={eventTypeObj} dataSource={roomData} fields= placeholder="Choose Type" index={0} popupHeight="200px" />
</div>
<div className="content-area">
<TextBoxComponent id="notes" ref={notesObj} placeholder="Notes" />
</div>
</div>
:
<div className="event-content">
<div className="meeting-type-wrap">
<label>Subject</label>:
<span>{props.Subject}</span>
</div>
<div className="meeting-subject-wrap">
<label>Type</label>:
<span>{getEventType(props)}</span>
</div>
<div className="notes-wrap">
<label>Notes</label>:
<span>{props.Description}</span>
</div>
</div>}
</div>);
}
const footerTemplate = (props) => {
return (<div className="quick-info-footer">
{props.elementType === "cell" ?
<div className="cell-footer">
<ButtonComponent id="more-details" cssClass='e-flat' content="More Details" onClick={buttonClickActions.bind(this)} />
<ButtonComponent id="add" cssClass='e-flat' content="Add" isPrimary={true} onClick={buttonClickActions.bind(this)} />
</div>
:
<div className="event-footer">
<ButtonComponent id="delete" cssClass='e-flat' content="Delete" onClick={buttonClickActions.bind(this)} />
<ButtonComponent id="more-details" cssClass='e-flat' content="More Details" isPrimary={true} onClick={buttonClickActions.bind(this).bind(this)} />
</div>}
</div>);
}
const quickInfoTemplates = {
header: headerTemplate,
content: contentTemplate,
footer: footerTemplate
};
const getResourceData = (data) => {
const resources = scheduleObj.current.getResourceCollections().slice(-1)[0];
const resourceData = resources.dataSource.filter((resource) => resource.Id === data.RoomId)[0];
return resourceData;
}
const getHeaderStyles = (data) => {
if (data.elementType === 'cell') {
return { alignItems: 'center', color: '#919191' };
}
else {
const resourceData = getResourceData(data);
return { background: resourceData.Color, color: '#FFFFFF' };
}
}
const getHeaderTitle = (data) => {
return (data.elementType === 'cell') ? 'Add Appointment' : 'Appointment Details';
}
const getHeaderDetails = (data) => {
return intl.formatDate(data.StartTime, { type: 'date', skeleton: 'full' }) + ' (' +
intl.formatDate(data.StartTime, { skeleton: 'hm' }) + ' - ' +
intl.formatDate(data.EndTime, { skeleton: 'hm' }) + ')';
}
const getEventType = (data) => {
const resourceData = getResourceData(data);
return resourceData.Name;
}
const buttonClickActions = (e) => {
const quickPopup = scheduleObj.current.element.querySelector('.e-quick-popup-wrapper');
const getSlotData = () => {
const cellDetails = scheduleObj.current.getCellDetails(scheduleObj.current.getSelectedElements());
const addObj = {};
addObj.Id = scheduleObj.current.getEventMaxID();
addObj.Subject = titleObj.current.value;
addObj.StartTime = new Date(+cellDetails.startTime);
addObj.EndTime = new Date(+cellDetails.endTime);
addObj.Description = notesObj.current.value;
addObj.RoomId = eventTypeObj.current.value;
return addObj;
};
if (e.target.id === 'add') {
const addObj = getSlotData();
scheduleObj.current.addEvent(addObj);
}
else if (e.target.id === 'delete') {
const eventDetails = scheduleObj.current.activeEventData.event;
let currentAction = 'Delete';
if (eventDetails.RecurrenceRule) {
currentAction = 'DeleteOccurrence';
}
scheduleObj.current.deleteEvent(eventDetails, currentAction);
}
else {
const isCellPopup = quickPopup.firstElementChild.classList.contains('e-cell-popup');
const eventDetails = isCellPopup ? getSlotData() :
scheduleObj.current.activeEventData.event;
let currentAction = isCellPopup ? 'Add' : 'Save';
if (eventDetails.RecurrenceRule) {
currentAction = 'EditOccurrence';
}
scheduleObj.current.openEditor(eventDetails, currentAction, true);
}
scheduleObj.current.closeQuickInfoPopup();
}
return (<div className='schedule-control-section'>
<div className='col-lg-12 control-section'>
<div className='control-wrapper'>
<ScheduleComponent id="schedule" cssClass='quick-info-template' ref={scheduleObj} height="650px" selectedDate={new Date(2020, 0, 9)} eventSettings={eventSettings} quickInfoTemplates={quickInfoTemplates}>
<ResourcesDirective>
<ResourceDirective field='RoomId' title='Room Type' name='MeetingRoom' textField='Name' idField='Id' colorField='Color' dataSource={roomData}></ResourceDirective>
</ResourcesDirective>
<Inject services={[Day, Week, WorkWeek, Month, Agenda, MonthAgenda]} />
</ScheduleComponent>
</div>
</div>
</div>);
}
;
const root = ReactDOM.createRoot(document.getElementById('schedule'));
root.render(<App />);
import { useRef } from 'react';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
ScheduleComponent, ResourcesDirective, ResourceDirective, Day, Week, WorkWeek, Month,
Agenda, MonthAgenda, Inject, ResourcesModel, CellClickEventArgs, CurrentAction, EventSettingsModel
} from '@syncfusion/ej2-react-schedule';
import { Internationalization } from '@syncfusion/ej2-base';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { TextBoxComponent } from '@syncfusion/ej2-react-inputs';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { ScheduleData } from './datasource';
const App = () => {
const eventTypeObj = useRef<DropDownListComponent>(null);
const titleObj = useRef<TextBoxComponent>(null);
const notesObj = useRef<TextBoxComponent>(null);
const scheduleObj = useRef<ScheduleComponent>(null);
const intl: Internationalization = new Internationalization();
const headerTemplate = (props: { [key: string]: Date }): JSX.Element => {
return (
<div className="quick-info-header">
<div className="quick-info-header-content" style={getHeaderStyles(props)}>
<div className="quick-info-title">{getHeaderTitle(props)}</div>
<div className="duration-text">{getHeaderDetails(props)}</div>
</div>
</div>
);
}
const contentTemplate = (props: { [key: string]: string }): JSX.Element => {
return (
<div className="quick-info-content">
{props.elementType === 'cell' ?
<div className="e-cell-content">
<div className="content-area">
<TextBoxComponent id="title" ref={titleObj} placeholder="Title" />
</div>
<div className="content-area">
<DropDownListComponent id="eventType" ref={eventTypeObj} dataSource={roomData}
fields= placeholder="Choose Type" index={0} popupHeight="200px" />
</div>
<div className="content-area">
<TextBoxComponent id="notes" ref={notesObj} placeholder="Notes" />
</div>
</div>
:
<div className="event-content">
<div className="meeting-type-wrap">
<label>Subject</label>:
<span>{props.Subject}</span>
</div>
<div className="meeting-subject-wrap">
<label>Type</label>:
<span>{getEventType(props)}</span>
</div>
<div className="notes-wrap">
<label>Notes</label>:
<span>{props.Description}</span>
</div>
</div>
}
</div>
);
}
const footerTemplate = (props: { [key: string]: Object }): JSX.Element => {
return (
<div className="quick-info-footer">
{props.elementType === "cell" ?
<div className="cell-footer">
<ButtonComponent id="more-details" cssClass='e-flat' content="More Details" onClick={buttonClickActions.bind(this)} />
<ButtonComponent id="add" cssClass='e-flat' content="Add" isPrimary={true} onClick={buttonClickActions.bind(this)} />
</div>
:
<div className="event-footer">
<ButtonComponent id="delete" cssClass='e-flat' content="Delete" onClick={buttonClickActions.bind(this)} />
<ButtonComponent id="more-details" cssClass='e-flat' content="More Details" isPrimary={true} onClick={buttonClickActions.bind(this).bind(this)} />
</div>
}
</div>
);
}
const roomData: { [key: string]: Object }[] = [
{ Name: 'Jammy', Id: 1, Capacity: 20, Color: '#ea7a57', Type: 'Conference' },
{ Name: 'Tweety', Id: 2, Capacity: 7, Color: '#7fa900', Type: 'Cabin' },
{ Name: 'Nestle', Id: 3, Capacity: 5, Color: '#5978ee', Type: 'Cabin' },
{ Name: 'Phoenix', Id: 4, Capacity: 15, Color: '#fec200', Type: 'Conference' },
{ Name: 'Mission', Id: 5, Capacity: 25, Color: '#df5286', Type: 'Conference' },
{ Name: 'Hangout', Id: 6, Capacity: 10, Color: '#00bdae', Type: 'Cabin' },
{ Name: 'Rick Roll', Id: 7, Capacity: 20, Color: '#865fcf', Type: 'Conference' },
{ Name: 'Rainbow', Id: 8, Capacity: 8, Color: '#1aaa55', Type: 'Cabin' },
{ Name: 'Swarm', Id: 9, Capacity: 30, Color: '#df5286', Type: 'Conference' },
{ Name: 'Photogenic', Id: 10, Capacity: 25, Color: '#710193', Type: 'Conference' }
];
const eventSettings: EventSettingsModel = { dataSource: ScheduleData };
const quickInfoTemplates = {
header: headerTemplate,
content: contentTemplate,
footer: footerTemplate
};
const getResourceData = (data: { [key: string]: Object }): { [key: string]: Object } => {
const resources: ResourcesModel = scheduleObj.current.getResourceCollections().slice(-1)[0];
const resourceData: { [key: string]: Object } = (resources.dataSource as Object[]).filter((resource: { [key: string]: Object }) =>
resource.Id === data.RoomId)[0] as { [key: string]: Object };
return resourceData;
}
const getHeaderStyles = (data: { [key: string]: Object }): Object => {
if (data.elementType === 'cell') {
return { alignItems: 'center', color: '#919191' };
} else {
const resourceData: { [key: string]: Object } = getResourceData(data);
return { background: resourceData.Color, color: '#FFFFFF' };
}
}
const getHeaderTitle = (data: { [key: string]: Object }): string => {
return (data.elementType === 'cell') ? 'Add Appointment' : 'Appointment Details';
}
const getHeaderDetails = (data: { [key: string]: Date }): string => {
return intl.formatDate(data.StartTime, { type: 'date', skeleton: 'full' }) + ' (' +
intl.formatDate(data.StartTime, { skeleton: 'hm' }) + ' - ' +
intl.formatDate(data.EndTime, { skeleton: 'hm' }) + ')';
}
const getEventType = (data: { [key: string]: string }): string => {
const resourceData: { [key: string]: Object } = getResourceData(data);
return resourceData.Name as string;
}
const buttonClickActions = (e: Event) => {
const quickPopup: HTMLElement = scheduleObj.current.element.querySelector('.e-quick-popup-wrapper') as HTMLElement;
const getSlotData: Function = (): { [key: string]: Object } => {
const cellDetails: CellClickEventArgs = scheduleObj.current.getCellDetails(scheduleObj.current.getSelectedElements());
const addObj: { [key: string]: Object } = {};
addObj.Id = scheduleObj.current.getEventMaxID();
addObj.Subject = titleObj.current.value;
addObj.StartTime = new Date(+cellDetails.startTime);
addObj.EndTime = new Date(+cellDetails.endTime);
addObj.Description = notesObj.current.value;
addObj.RoomId = eventTypeObj.current.value;
return addObj;
};
if ((e.target as HTMLElement).id === 'add') {
const addObj: { [key: string]: Object } = getSlotData();
scheduleObj.current.addEvent(addObj);
} else if ((e.target as HTMLElement).id === 'delete') {
const eventDetails: { [key: string]: Object } = scheduleObj.current.activeEventData.event as { [key: string]: Object };
let currentAction: CurrentAction = 'Delete';
if (eventDetails.RecurrenceRule) {
currentAction = 'DeleteOccurrence';
}
scheduleObj.current.deleteEvent(eventDetails, currentAction);
} else {
const isCellPopup: boolean = (quickPopup.firstElementChild as HTMLElement).classList.contains('e-cell-popup');
const eventDetails: { [key: string]: Object } = isCellPopup ? getSlotData() :
scheduleObj.current.activeEventData.event as { [key: string]: Object };
let currentAction: CurrentAction = isCellPopup ? 'Add' : 'Save';
if (eventDetails.RecurrenceRule) {
currentAction = 'EditOccurrence';
}
scheduleObj.current.openEditor(eventDetails, currentAction, true);
}
scheduleObj.current.closeQuickInfoPopup();
}
return (
<div className='schedule-control-section'>
<div className='col-lg-12 control-section'>
<div className='control-wrapper'>
<ScheduleComponent id="schedule" cssClass='quick-info-template' ref={scheduleObj} height="650px"
selectedDate={new Date(2020, 0, 9)} eventSettings={eventSettings} quickInfoTemplates={quickInfoTemplates}>
<ResourcesDirective>
<ResourceDirective field='RoomId' title='Room Type' name='MeetingRoom' textField='Name' idField='Id'
colorField='Color' dataSource={roomData}></ResourceDirective>
</ResourcesDirective>
<Inject services={[Day, Week, WorkWeek, Month, Agenda, MonthAgenda]} />
</ScheduleComponent>
</div>
</div>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById('schedule'));
root.render(<App />);
<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Schedule</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-base/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-buttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-calendars/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-dropdowns/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-inputs/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-navigations/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-popups/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/31.1.17/ej2-react-schedule/styles/material.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<link href="index.css" rel="stylesheet" />
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='schedule'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>