Our powerful JS Calendar component


Post by mpost »

We are using the Bryntum Calendar to display and edit events that are already available on the client-side. For event change tracking, we are utilizing the CrudManager and its hasChanges callback. However, we are encountering unexpected behavior when using hasChanges , as demonstrated in the following code snippet.

calendar = new Calendar({
  appendTo: calendarElement,
  crudManager: {
    listeners: {
      hasChanges({ source: crudManager }) {
        console.log('hasChanges', crudManager.changes);
        crudManager.acceptChanges();
        // sendAllEventsToRemoteServer();
      },
    },
  },
});

Steps to Reproduce:

  1. Initialize the Bryntum Calendar with the CrudManager and hasChanges listener.
  2. Add a new event via the event editor and click "save."
    • Expected: The hasChanges callback is triggered, and crudManager.changes contains an entry for the newly added event with a phantomId.
    • Action: We call crudManager.acceptChanges() to consume the changes.
  3. Create a second event by dragging in the calendar.
    • Unexpected behavior: The hasChanges callback fires again, but this time crudManager.changes contains an entry for the event that was previously saved in step 2, despite the call to acceptChanges().

Expected Behavior:
When calling crudManager.acceptChanges(), we expect the changes from the previous event to be consumed and cleared. The crudManager.changes should not include the already added event when creating a new one.

Actual Behavior:
After calling acceptChanges() following the addition of the first event, the hasChanges callback is triggered again when creating a new event, and the crudManager.changes object unexpectedly contains the same event from the previous step.

Environment:

  • Bryntum Calendar Version: 6.0.5
  • Browser: Chrome
  • OS: Windows 10

Post by Animal »

I cannot reproduce this by adding that listener locally. When I drag-create a new event, I get that newly created event wit it's phantom id as the only item in `changes.

Is there other code in the app?

Screenshot 2024-09-06 at 18.04.35.png
Screenshot 2024-09-06 at 18.04.35.png (885.5 KiB) Viewed 283 times

Post by Animal »

Something that i do see that probably should not is that the actual drag start, when creating the tentative drag-creating event which is not in the store, ends up in that listener with the CrudManager seeing changes.

That is not good. Is that the real issue tat you are seeing? The as yet, unadded drag-create event getting through to the changes listener?


Post by Animal »

Hm no, there is something extra going on. I do see a drag-created event go through there twice.On add of a second new event, I hit that breakpoint anch changes.added has the last event added. Not the one that's just been added and is being edited.


Post by Animal »


Post by Animal »

As a workaround I suggest ths following:

        listeners: {
            hasChanges : {
                fn({ source: crudManager }) {
                    console.log('hasChanges', crudManager.changes);
                    crudManager.acceptChanges();
                    // sendAllEventsToRemoteServer();
                },
                buffer : 1000
            }
        }

So that multiple hasChanges events firing within 1000ms are coalesced. The CrudManager should probably fire its hasChanges events like that anyway. If multiple changes are being made quickly in response to other changes, then not every one has to go to the backend separately. It's the end state of all the data manipulation that needs to be saved.


Post by mpost »

Thank you for the prompt response. The workaround of buffering for 1000ms does resolve the changed state, but unfortunately, it introduces a side effect. If an event editor is opened during the buffering period, it gets closed because we update the event's ID in hasChanges.

To update the id we run:

    crudManager.suspendChangeTracking()
    eventStore.applyChangeset({
      added: changes.events.added?.map((change) => ({
        $PhantomId: change.$PhantomId,
        id: createId(),
      })),
    })
    crudManager.resumeChangeTracking(true)
    

Post by alex.l »

Sorry, I don't follow what do you mean.
Could you please describe in "Steps to reproduce" format with expected and actual results described.

All the best,
Alex


Post Reply