我试图将Fullcalendar的React组件变成Inductive Automation的Ignition平台中的一个组件。这相对顺利,一切都正确呈现,除了timeGridWeek
.
每当我尝试导航到timeGridWeek
时,控制台都会吐出一个对我来说意义不大的错误,整个日历停止响应。 这是有问题的错误:
RadComponents.js?no_…e=1579268884233:960 Uncaught TypeError: Cannot read property 'years' of null
at wholeDivideDurations (RadComponents.js?no_…e=1579268884233:960)
at TimeGrid.../../node_modules/@fullcalendar/timegrid/main.esm.js.TimeGrid.processOptions (RadComponents.js?no_…1579268884233:13228)
at new TimeGrid (RadComponents.js?no_…1579268884233:13207)
at TimeGridView [as constructor] (RadComponents.js?no_…1579268884233:13757)
at new TimeGridView (RadComponents.js?no_…1579268884233:14010)
at CalendarComponent.../../node_modules/@fullcalendar/core/main.esm.js.CalendarComponent.renderView (RadComponents.js?no_…=1579268884233:6501)
at CalendarComponent.../../node_modules/@fullcalendar/core/main.esm.js.CalendarComponent.render (RadComponents.js?no_…=1579268884233:6453)
at CalendarComponent.../../node_modules/@fullcalendar/core/main.esm.js.Component.receiveProps (RadComponents.js?no_…=1579268884233:4138)
at Calendar.../../node_modules/@fullcalendar/core/main.esm.js.Calendar.renderComponent (RadComponents.js?no_…=1579268884233:7068)
at Calendar.../../node_modules/@fullcalendar/core/main.esm.js.Calendar.executeRender (RadComponents.js?no_…=1579268884233:7025)
现在,错误对我来说意义不大的原因是因为它似乎发生在TimeGridPlugin
本身中,我认为我无法访问。
这是我的代码:
import * as React from 'react';
import { Component, ComponentMeta, ComponentProps, SizeObject } from '@inductiveautomation/perspective-client';
import { Calendar } from '@fullcalendar/core';
import FullCalendar from '@fullcalendar/react';
import timeGridPlugin from '@fullcalendar/timegrid';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
// the 'key' or 'id' for this component type. Component must be registered with this EXACT key in the Java side as well
// as on the client side. In the client, this is done in the index file where we import and register through the
// ComponentRegistry provided by the perspective-client API.
export const COMPONENT_TYPE = "react-display-calendar";
// this is the shape of the properties we get from the perspective 'props' property tree.
export interface ReactCalendarProps {
editable: boolean;
selectable: boolean;
defaultView: string;
events: Array<object>;
firstDay: number;
eventLimit: boolean | number;
minTime: string;
maxTime: string;
weekNumbers: boolean;
weekNumbersWithinDays: boolean;
nowIndicator: boolean;
slotDuration: string;
allDayText: string;
longPressDelay: number;
}
export class ReactCalendar extends Component<ComponentProps, any> {
calendar: Calendar;
private calendarComponentRef = React.createRef<any>();
render() {
const {props} = this.props;
const allDayTextProp = props.readString('allDayText');
const eventsProp = props.readArray('events');
const editableProp = props.readBoolean('editable');
const selectableProp = props.readBoolean('selectable');
const firstDayProp = props.readNumber('firstDay', 1);
const eventLimitProp = props.read('eventLimit');
const weekNumbersProp = props.readBoolean('weekNumbers');
const weekNumbersWithinDaysProp = props.readBoolean('weekNumbersWithinDays');
const nowIndicatorProp = props.readBoolean('nowIndicator');
const defaultViewProp = props.readString('defaultView');
const minTimeProp = props.readString('minTime');
const maxTimeProp = props.readString('maxTime');
const slotDurationProp = props.readString('slotDuration');
const longPressDelayProp = props.readNumber('longPressDelay', 1000);
const pluginsProp = [dayGridPlugin, timeGridPlugin, interactionPlugin];
const headerProp = { left: 'dayGridMonth,timeGridWeek,timeGridDay', center: 'title', right: 'today, ,prev,next' };
const eventTimeFormatProp = { hour: '2-digit', minute: '2-digit', meridiem: false, hour12: false };
const slotLabelFormatProp = { hour: '2-digit', minute: '2-digit', meridiem: false, hour12: false };
return(
<FullCalendar
{...this.props.emit()}
ref={this.calendarComponentRef}
plugins={pluginsProp}
header={headerProp}
eventTimeFormat={eventTimeFormatProp}
slotLabelFormat={slotLabelFormatProp}
defaultView={defaultViewProp}
height="parent"
contentHeight="auto"
allDayText={allDayTextProp}
events={eventsProp}
editable={editableProp}
eventStartEditable={editableProp}
eventDurationEditable={editableProp}
selectable={selectableProp}
firstDay={firstDayProp}
eventLimit={eventLimitProp}
weekNumbers={weekNumbersProp}
weekNumbersWithinDays={weekNumbersWithinDaysProp}
nowIndicator={nowIndicatorProp}
minTime={minTimeProp}
maxTime={maxTimeProp}
slotDuration={slotDurationProp}
longPressDelay={longPressDelayProp}
select={this.handleSelect}
windowResize={this.handleWindowResize}
eventDrop={this.handleEventDrop}
eventClick={this.handleEventClick}
eventResize={this.handleEventResize}
/>
);
}
handleSelect = (arg: any) => {
let selectStart = arg.start.valueOf() / 1000 + 3600;
let selectEnd = arg.end.valueOf() / 1000 + 3600;
if (!isNaN(arg.start.valueOf())) {
this.props.componentEvents.fireComponentEvent("onSelectionMade", {start: selectStart, end: selectEnd});
} else {
alert('Invalid date.');
}
}
handleWindowResize = (arg: any) => {
this.props.componentEvents.fireComponentEvent("onWindowResize", {arg});
}
handleEventDrop = (arg: any) => {
if (arg.event.start != null && arg.event.end != null) {
let eventId = arg.event.id;
let startTime = arg.event.start.valueOf() / 1000 + 3600;
let endTime = arg.event.end.valueOf() / 1000 + 3600;
this.props.componentEvents.fireComponentEvent("onEventDropped", {
id: eventId,
start: startTime,
end: endTime
});
}
}
handleEventClick = (arg: any) => {
let title = arg.event.title;
let id = arg.event.id;
this.props.componentEvents.fireComponentEvent("onEventClick", {
title,
id
});
}
handleEventResize = (arg: any) => {
if (arg.event.start != null && arg.event.end != null) {
let eventId = arg.event.id;
let startTime = arg.event.start.valueOf() / 1000 + 3600;
let endTime = arg.event.end.valueOf() / 1000 + 3600;
this.props.componentEvents.fireComponentEvent("onEventResized", {
id: eventId,
start: startTime,
end: endTime
});
}
}
}
// this is the actual thing that gets registered with the component registry
export class ReactCalendarMeta implements ComponentMeta {
getComponentType(): string {
return COMPONENT_TYPE;
}
// the class or React Type that this component provides
getViewClass(): React.ReactType {
return ReactCalendar;
}
getDefaultSize(): SizeObject {
return ({
width: 360,
height: 360
});
}
}
以前有人遇到过这个问题吗?任何想法都值得赞赏!
所以,事实证明 React 版本需要slotDuration
的默认值。否则,在timeGridWeek
的第一次渲染过程中,大量的值将是未定义的或为空的,从而破坏日历。