Our pure JavaScript Scheduler component


Post by jorgeduarterekyl »

I'm working with Bryntum Scheduler Pro and currently implementing recurring event support. I have a question regarding the best way to handle custom data control when a recurring event is split after the user chooses "Edit this occurrence" or "Edit all future occurrences".

When a split occurs:

A new EventModel and associated AssignmentModel are created automatically and the old one updated from what I'm getting is the workflow. Correct me if I'm wrong.

I need to capture and control the data of these newly created records for the event and the assignment and send them through one only endpoint so I can save it in the database with the correct ID's.

First I did it with 2 different listeners (one for the EventStore.on.beforeAdd and another AssignmentStore.on.beforeAdd) and 2 different endpoints but I'm having problems cause my endpoits are async so they will run at the same time causing it to break.

I need some help on how to do this cause I'm currently in the dark on the best way to handle this.

Thank you :)


Post by marcio »

Hey Jorge,

Thanks for reaching out.

Perhaps you could use the https://bryntum.com/products/schedulerpro/docs/api/SchedulerPro/feature/TaskEdit#event-beforeEventSave event handler to capture changes before they are saved. This event allows you to modify the event data before it is committed to the store. You can then consolidate the data from both the EventModel and AssignmentModel and send it to a single endpoint. You can use the folllowing approach:

  1. Use the beforeEventSave event to capture the event data before it is saved.
  2. Modify the event data as needed.
  3. Use a single endpoint to send the consolidated data for both the event and assignment.

Here's a code snippet to illustrate:

scheduler.on('beforeEventSave', async ({ eventRecord }) => {
    // Modify eventRecord as needed
    const eventData = eventRecord.data;

    // Fetch related assignment data
    const assignmentData = scheduler.assignmentStore.getAssignmentsForEvent(eventRecord);

    // Consolidate data
    const dataToSend = {
        event: eventData,
        assignments: assignmentData
    };

    // Send to your endpoint
    await sendToEndpoint(dataToSend);
});

This way, you ensure that both the event and its assignments are processed together, avoiding issues with asynchronous operations.

If that doesn't solve your issue, please let us know.

Best regards,
Márcio

How to ask for help? Please read our Support Policy


Post by jorgeduarterekyl »

Hey,

Thanks for the answer marcio.

I have my listeners done like this:

eventStore.on({
            beforeEventSave: ({record}: any) => {
                console.log('event save')
                if (!this.isAddingEvent) {
                    const assignmentRecord = this.assignmentStore.getAssignmentsForEvent(record);
                    const lastScheduleRecord = this.project.eventStore.last;
                    let newEventId = 1;
                    if (lastScheduleRecord) {
                        newEventId = Math.max(...this.project.assignmentStore.getRange().map((assignment: any) => assignment.id)) + 1;
                    }
                    record.set({
                        id: newEventId
                    });
                    this.addEventAndSendToSignalR(record, assignmentRecord);
                } else {
                    this.isAddingEvent = false;
                }
            },
            update: ({ record, changes }: any) => {
                console.log('update')
                if (!this.isExternalUpdate) {
                    const assignmentRecord = this.assignmentStore.getAssignmentsForEvent(record);
                    if ('duration' in changes || 'startDate' in changes || 'durationUnit' in changes || 'note' in changes || 'recurrenceRule' in changes) {
                        if (assignmentRecord[0]) {
                            this.sendUpdateToSignalR(record, assignmentRecord[0]);
                        }
                    }  
} else { this.isExternalUpdate = false; } }, beforeRemove: ({ records }: any) => { this.isStandBy = true; records.forEach((record: any) => { this.deleteEventAndAssignmentsAndSendToSignalR(record); }); }, }); //Listeners on the AssignmentStore assignmentStore.on({ beforeAdd: ({records}: any) => { console.log('assignment') if (!this.isAddingAssignment) { if (records) { records.forEach((record: any) => { const lastScheduleRecord = this.project.assignmentStore.last; let newAssignmentId = 1; if (lastScheduleRecord) { newAssignmentId = Math.max(...this.project.assignmentStore.getRange().map((assignment: any) => assignment.id)) + 1; } record.set({ id: newAssignmentId }); this.addAssignmentAndSendToSignalR(record); }); } } else { this.isAddingAssignment = false; } }, update: ({ record, changes }: any) => { this.isExternalUpdate = true; if ('resourceId' in changes ) { const eventRecord : any = this.eventStore.getById(record.eventId); if (eventRecord) { this.sendUpdateToSignalR(eventRecord, record); } } }, beforeRemove: ({records}:any) =>{ if (!this.isStandBy) { var event = this.eventStore.getById(records[0].eventId) if (this.eventStore.getAssignmentsForEvent(event as SchedulerEventModel).length > 1) { records.forEach((record: any) => { if (record) { this.deleteAssignmentAndSendToSignalR(record); } }); return true; } else { const errorUnassignment = this._translocoService.translate('VEC:BryntumUnassignment') if (!this.messageSent) { this.messageSent = true; if (scheduler.features.taskEdit.isEditing) { //@ts-ignore this.scheduler.features.taskEdit.editor.close(); } Toast.show({ html: errorUnassignment, timeout: 10000, style: 'color: red' }); return false; } else { this.messageSent = false; return false; } } } else { this.isStandBy = false; return true; } }, });

So I can handle all the creates, updates and deletes from assignments and events.
Doing that will make it so the assignment add is fired before and one thing I noticed is that when we do that it will fire the beforeAdd from the assignment then the update from the event 2 times.
If I do this with a beforeAdd but using the same example you gave will it work to?

Best regards
Jorge


Post by alex.l »

Hi Jorge,

You can check it, I believe it will work the same.
Any reason to not use 'change' events of each store you need to manage these things? Did you use CrudManager or managed to sync data by your own? Are you noticed about project.changes prop that contains all not committed changes?
https://bryntum.com/products/schedulerpro/docs/api/SchedulerPro/model/ProjectModel#property-changes
https://bryntum.com/products/schedulerpro/docs/api/SchedulerPro/data/EventStore#event-change

All the best,
Alex Lazarev

How to ask for help? Please read our Support Policy

We do not write the code in bounds of forum support. If you need help with development, contact us via bryntum.com/services


Post Reply