In the react application I am working on, we have the scheduler wrapped as a react component that receives events and resources and props. Every time the events or resources update, the bryntum engine gets updated similarly to your react example.
this.schedulerEngine.resources = props.resources;
this.schedulerEngine.eventStore.data = props.events;
Now, every time that events update, the row gets raised in height for the value of a single event.
This is the initial state. And this is the state after new events get loaded. Those events are constructed outside of the BryntumScheduler component. They are subclasses of EventModel and they get initialized before render. Resources are of type tree and they are subclasses of the ResourceModel. An important thing to possibly stand out is that loaded events can be the same, just constructed again on render and they will still produce this bug.
Below is a pseudo typescript example of what is actually going on outside BryntumScheduler.
class FooResource extends ResourceModel {
static get fields() {
return [{ name: "name", dataSource: "foo" }];
}
constructor(resource: RawResource) {
super(resource);
}
}
class FooEvent extends EventModel {
static get fields() {
return [
{
name: "resourceId",
dataSource: "foo.bar.id",
},
{
name: "startDate",
dataSource: "computedDateFrom",
},
{
name: "endDate",
dataSource: "computedDateTo",
},
];
}
constructor(event: RawEvent) {
super(event);
}
}
export class MyScheduler extends React.Component {
public render() {
const resources = this.createResources(this.props.rawResources);
const events = this.createEvents(this.props.rawEvents);
return (
<div>
<BryntumScheduler
resources={resources}
events={events}
columns={this.createColumns()}
features={{ tree: true }}
/>
</div>
);
}
private createColumns() {
return [
{
field: "name",
text: "text",
type: "tree",
expandedFolderIconCls: null,
collapsedFolderIconCls: null,
leafIconCls: null,
width: "15%",
id: "my-id",
},
];
}
private createResources(rawResources) {
return rawResources.map((resource) => {
return new FooResource(resource);
});
}
private createEvents(rawEvents) {
return rawEvents.map((event) => {
return new FooEvent(event);
});
}
}
import * as React from "react";
import { Scheduler } from "bryntum-scheduler/scheduler.umd.js";
import { BryntumSchedulerProps } from "./interfaces/BryntumSchedulerProps";
import "bryntum-scheduler/scheduler.stockholm.css";
import autobind from "autobind-decorator";
export class BryntumScheduler extends React.Component<BryntumSchedulerProps> {
public static defaultProps: Partial<BryntumSchedulerProps> = {
autoWidthColumnsWithId: [],
extendTimelineDayCount: 3,
zoomOnMouseWheel: true,
};
public el: HTMLElement | null;
private schedulerEngine: Scheduler;
public componentWillUnmount() {
this.schedulerEngine.destroy();
}
// tslint:disable-next-line:newspaper-order
public componentDidMount(): void {
if (this.el === null) {
throw new Error(
"Container div is null, can not instantiate scheduler",
);
}
this.schedulerEngine = new Scheduler({
height: this.props.height,
// rowHeight: 60,
// barMargin: 0,
appendTo: this.el,
columns: this.props.columns,
events: this.props.events,
resources: this.props.resources,
// startDate: this.props.startDate,
// endDate: this.props.endDate,
// emptyText: SchedulerMessage.EmptyRows,
// viewPreset: ViewPreset.DayAndWeek,
features: this.props.features,
autoAdjustTimeAxis: false,
zoomOnMouseWheel: this.props.zoomOnMouseWheel,
zoomOnTimeAxisDoubleClick: false,
// minZoomLevel: 9,
// maxZoomLevel: 10,
// callOnFunctions: true,
});
}
public render() {
return <div ref={(el) => (this.el = el)} />;
}
public componentDidUpdate(prevProps: BryntumSchedulerProps) {
this.updateEngineProperties(prevProps);
}
@autobind
private updateEngineProperties(prevProps: BryntumSchedulerProps) {
this.schedulerEngine.resources = this.props.resources;
this.schedulerEngine.eventStore.data = this.props.events;
if (prevProps.startDate !== this.props.startDate) {
this.schedulerEngine.startDate = this.props.startDate;
}
if (prevProps.endDate !== this.props.endDate) {
this.schedulerEngine.endDate = this.props.endDate;
}
}
}
I've constructed a simple test case that actually does not reproduce the aforementioned error, but creates a similar one.
Steps for installation:
1. extract scheduler-2.0.2 to vendor directory
2. npm install
Steps to reproduce:
1. before zooming click on update events
2. zoom out timeline
The bug that occurs should show only new events that are rendered in the scheduler, but instead it shows filled rows with unclickable events. If if zoom out first and them click on update events that but is not present. With this example I tried to replicate our case, but did not get the bug that I described on the start of this post. Also, if I remove the viewPreset key from options config, events accumulate if I don't zoom out before update, but get reset to correct state after the zooming out.
Could you tell what is wrong with the examples I gave you? Am I maybe constructing resource and event models wrong?