Bryntum: Fixing Recurring & Nested Event Error

Alex Johnson
-
Bryntum: Fixing Recurring & Nested Event Error

Introduction

This article addresses a critical issue encountered while using Bryntum Scheduler Pro: an error that arises when combining recurring events and nested events. This problem, highlighted in a forum post, manifests as a TypeError within the NestedEvents.js file. Understanding the root cause and potential solutions is crucial for developers aiming to leverage the full capabilities of Bryntum Scheduler Pro in their projects. This article provides an in-depth look at the problem, its context, and possible workarounds, ensuring you can effectively implement both recurring and nested events in your scheduling applications.

The Problem: TypeError with Recurring and Nested Events

The core issue presents itself as a TypeError with the message "Cannot read properties of undefined (reading 'isRoot')" within the NestedEvents.js file. This error occurs specifically when the nested events feature is enabled in conjunction with recurring events. A demo illustrating the problem is available in the recurrenceWithNestedEvents.zip file. The error trace points to line 798 of NestedEvents.js, indicating a problem within the getEventsToRender function of the NestedEvents feature.

This error suggests a compatibility issue between the way Bryntum Scheduler Pro handles recurring events and nested events. Nested events, which represent hierarchical relationships between events, appear to conflict with the logic used to render recurring events. The absence of explicit documentation stating the incompatibility of these features further complicates the matter. This means developers might unknowingly attempt to combine these features, only to encounter this runtime error. The key takeaway here is that combining recurring events with nested events in Bryntum Scheduler Pro can lead to a TypeError, specifically when the system attempts to determine which events to render. This issue arises because the NestedEvents feature's logic for filtering and displaying events doesn't fully account for the complexities introduced by recurring events, particularly how they are structured and managed within the scheduler's data store. Addressing this requires a deeper understanding of the internal workings of both features and how they interact with each other.

Root Cause Analysis

To understand why this error occurs, let's delve deeper into the scenario. When tree: true is set in the event store configuration, the scheduler attempts to render events in a hierarchical manner. However, with recurring events, the scheduler needs to handle multiple instances of the same event based on the recurrence rule. This creates a complex data structure where nested events and recurring event instances interact, leading to the error. The getEventsToRender function, responsible for filtering and preparing events for display, fails to correctly process this combination, resulting in the "Cannot read properties of undefined" error. This happens because the function likely expects all events to have certain properties (like isRoot), which might not be consistently available for recurring event instances or their nested children. The provided code snippet, which attempts to overwrite the getEventsToRender function, highlights an effort to address this issue by manually filtering out events that cause the error. However, this workaround only partially solves the problem, as it prevents the error but also results in the nested children not being rendered. Therefore, the underlying cause is a mismatch in how the NestedEvents feature handles the data structure created by recurring events, specifically the interaction between parent-child relationships and recurring instances. The error stems from the NestedEvents feature's inability to correctly process the hierarchical structure of nested events in conjunction with the multiple instances generated by recurring events.

Developer's Attempted Solution and Its Limitations

The developer attempted to resolve the issue by overriding the getEventsToRender function, which is responsible for determining which events should be displayed in the scheduler. The provided code snippet demonstrates this attempt:

getEventsToRender(resourceRecord: ResourceModel, eventRecords: EventModel[]) {
 ArrayHelper.remove(
 eventRecords,
 ...eventRecords.filter((eventRecord: EventModel) =>
 eventRecord.isEventModel &&
 eventRecord.parent &&
 !eventRecord.parent.isRoot
 )
 );
 return eventRecords;
}

This code filters out event records that are children of non-root parents, aiming to prevent the error. While this approach does prevent the TypeError, it comes with a significant limitation: the nested child events are no longer rendered. This is because the filter removes these events from the list of events to be displayed. This workaround essentially sacrifices the nested events functionality to avoid the error, which is not an ideal solution for projects that require both recurring and nested events. The developer's workaround, while preventing the error, results in the nested child events not being rendered, highlighting the need for a more comprehensive solution. This approach underscores the complexity of the issue, as a simple fix can have unintended consequences on other aspects of the scheduler's functionality. A proper solution would need to address the underlying data structure incompatibility without sacrificing the display of nested events.

Understanding the Event Structure

To fully grasp the problem, it's essential to examine the structure of the events being used. The provided example event with a child illustrates the hierarchical relationship:

{
 "id": 1,
 "name": "Monday to Friday",
 "startDate": "2019-12-30",
 "durationUnit": "day",
 "duration": 4.5,
 "cls": "custom-event",
 "recurrenceRule": "FREQ=WEEKLY",
 "readOnly": true,
 "manuallyScheduled": true,
 "resourceId": "79c24ed6-860f-4846-be67-4a0ae9c5360b",
 "children": [
 {
 "id": 7,
 "name": "Child Event",
 "startDate": "2019-12-30",
 "duration": 1
 }
 ]
}

This JSON structure represents a recurring event (

You may also like