Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Id collision error when creating new event using an external button on EventList mode #7127

Closed
taauntik opened this issue Jul 6, 2023 · 0 comments
Assignees
Labels
bug Something isn't working forum Issues from forum high-priority Urgent to have fixed resolved Fixed but not yet released (available in the nightly builds)
Milestone

Comments

@taauntik
Copy link

taauntik commented Jul 6, 2023

Forum post

We are using EventList mode to render calendar events.

https://bryntum.com/products/calendar/examples/list-range/

When creating a new event using an external button, the following error is raised:

Store.js:1098 Uncaught Error: Id collision on _generatedModelClass_62ed44f1-691e-4c08-9424-99e3b96bb27e
    at Store.onDataReplaced (Store.js:1098:23)
    at Store.loadData (Store.js:1633:16)
    at Store.setStoreData (Store.js:1543:20)
    at set data [as data] (Store.js:1464:14)
    at EventList.populateStore (EventList.js:957:23)
    at EventList.populateStoreSoon [as populateStoreSoonNow] (EventList.js:910:20)
    at EventList.<anonymous> (Delayable.js:900:39)
    at EventList.invoker (Delayable.js:101:24)
    at Delayable.js:512:57

To reproduce it replace the whole code of the demo above with the code below

import { EventModel, DateHelper, Calendar } from '../../build/calendar.module.js?468921';
import shared from '../_shared/shared.module.js?468921';

// A custom Event class with a few extra fields. You can extend this to add any fields and methods you want.
class AppEvent extends EventModel {

    // Add some extra fields to demonstrate the createColumnsFromModel option of ColumnPicker
    static fields = [{
        name : 'notes',

        // Provide defaults for when a column is autocreated for this field
        column : {
            width  : '20em',
            editor : {
                type : 'textareapickerfield'
            }
        }
    }, {
        name : 'important',
        type : 'boolean'
    }];

    // Define field getter to enable grouping by the start date *not including time portion*
    get eventStartDate() {
        return this.get('eventStartDate') || DateHelper.startOf(this.startDate);
    }
}
const
    startDate = '2023-10-09',
    endDate   = '2023-10-23',
    calendar  = new Calendar({
        // Start life looking at this date
        date : new Date(2023, 9, 12),

        sidebar : {
            width : '20em',
            items : {
                // A container which encapsulates the start and end input fields
                rangeDisplay : {
                    type     : 'container',
                    weight   : 0,
                    defaults : {
                        editable : false,
                        triggers : {
                            expand : null
                        },
                        step          : '1d',
                        labelPosition : 'above',
                        flex          : 1,
                        listeners     : {
                            change : 'up.onRangeFieldChanged'
                        }
                    },
                    items : {
                        startDate : {
                            label  : 'Start',
                            type   : 'datefield',
                            value  : startDate,
                            format : 'MMM DD'
                        },
                        endDate : {
                            label  : 'End',
                            type   : 'datefield',
                            value  : endDate,
                            format : 'MMM DD'
                        }
                    }
                },
                datePicker : {
                    weight : 0,
                    type   : 'datepicker',

                    // In this mode, the "selection" is applied to any child
                    // EventList views - EventList and AgendaView
                    multiSelect : 'range',
                    selection   : [
                        startDate,
                        endDate
                    ],
                    listeners : {
                        selectionChange : 'up.onDatePickerRangeSelected'
                    }
                },
                resourceFilter : {
                    minHeight : null
                }
            }
        },

        modeDefaults : {
            startDate,
            endDate,

            // Disable picking a range using the list's UI.
            // We control the exact date range
            listRangeMenu : null
        },

        // Show only event lists
        modes : {
            day   : null,
            week  : null,
            month : null,
            year  : null,
            list  : {
                // If we use field names which the EventList creates for itself, our config
                // gets merged into the default, so we can affect the EventList's own columns.
                columns : [{
                    field : 'name',
                    flex  : '0 0 12em',
                    renderer({ record }) {
                        return [{
                            tag       : 'i',
                            className : 'b-icon b-icon-circle',
                            style     : `color:${record.resource?.eventColor}`
                        }, {
                            text : record.name
                        }];
                    }
                }],
                features : {
                    group : {
                        field : 'eventStartDate',
                        // Render the group date for the first (group field) column
                        renderer({ grid, rowElement, isFirstColumn, groupRowFor }) {
                            if (isFirstColumn) {
                                rowElement.dataset.date = DateHelper.makeKey(groupRowFor);
                                return DateHelper.format(groupRowFor, grid.dateFormat);
                            }
                        },
                        // We can't group by other fields, so disable all grouping menu options
                        populateHeaderMenu : () => {}
                    }
                }
            }
        },

        mode : 'list',

        // CrudManager arranges loading and syncing of data in JSON form from/to a web service
        crudManager : {
            loadUrl    : 'data/busy.json',
            // This demo uses a custom Event model with extra fields
            eventStore : {
                modelClass : AppEvent
            },
            autoLoad : true
        },

        appendTo : 'container',

        listeners : {
            rangeChange : 'this.onViewRangeChanged'
        },

        // When a calendar view announces that it has changed its range, ensure
        // our two input fields match
        onViewRangeChanged({ new : { startDate, endDate } }) {
            this.widgetMap.startDate.value = startDate;
            this.widgetMap.endDate.value = endDate;
        },

        // Respond to the two DateFields being changed - update the views
        onRangeFieldChanged() {
            this.eachView(v => v.setConfig({
                startDate : this.widgetMap.startDate.value,
                endDate   : this.widgetMap.endDate.value
            }));
        },

        // If the date picker selects a range, ensure
        // our two input fields match
        onDatePickerRangeSelected({ source,  selection : [startDate, endDate] }) {
            if (source.multiSelect === 'range') {
                this.widgetMap.startDate.value = startDate;
                this.widgetMap.endDate.value = endDate;
            }
        },

        tbar : {
            items : {
                addNew : {
                    type : 'button',
                    text : 'add new',
                    onAction({ source }) {
                        const calendar = source.parent.parent;
                        calendar.createEvent(calendar.date);
                    }
                }
            }
        }
    });

const btn = document.createElement('button');
btn.id = 'add-new';
btn.innerText = 'Add New';
document.querySelector('#container').appendChild(btn);
document.getElementById('add-new').addEventListener('click', function () {
    calendar.createEvent(calendar.date);
});

And here are the steps

Recording.2023-07-06.164546.mp4
@taauntik taauntik added bug Something isn't working forum Issues from forum labels Jul 6, 2023
@matsbryntse matsbryntse added the high-priority Urgent to have fixed label Jul 6, 2023
@mazzafabio mazzafabio self-assigned this Jul 17, 2023
@mazzafabio mazzafabio added in progress ready for review Issue is fixed, the pull request is being reviewed labels Jul 17, 2023
@isglass isglass added resolved Fixed but not yet released (available in the nightly builds) and removed in progress ready for review Issue is fixed, the pull request is being reviewed labels Jul 20, 2023
@isglass isglass added this to the 5.4.2 milestone Jul 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working forum Issues from forum high-priority Urgent to have fixed resolved Fixed but not yet released (available in the nightly builds)
Projects
None yet
Development

No branches or pull requests

4 participants