1

我试图将 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
        });
    }
}

有没有人遇到过这个问题?任何想法表示赞赏!

4

1 回答 1

1

因此,事实证明 React 版本需要slotDuration. 否则,在第一次渲染 时,大量的值将未定义或为空timeGridWeek,从而破坏了日历。

于 2020-01-21T14:26:12.393 回答