Our powerful JS Calendar component


Post by dansmithcreates »

thanks for pointing me in the direction of flat data. I think I am bit confused about the props data and the need for an event store. If I have this in my props:

    eventEditFeature: {
        items: {
...
            reminderGroup: {
                type: "buttongroup",
                name: "reminderGroup",
...
                    {
                        type: "button",
                        name: "reminders5Min",
                        toggleable: true,
                        text: "5 Min",
                        toggled: false,
                        cls: buttonClasses.value["5m"],
                        onToggle: onReminderToggle,
                    },

then I can do something to define the reminder fields to store, inline? Or do I have to define an eventstore? I think the only example I see is adding the 'notes' field to listview.

Is this the right direction? Just trying to understand the docs... I understand how to work with the event editor, but the docs on what to do with added fields / event store.. am not understanding those...

    // in the props
    crudManager: {
        eventStore: {
            fields: [
                { name: "reminders5min" },
                { name: "reminders15min" },
                { name: "reminders30min" },
                { name: "reminders55min" },
                { name: "reminders1hour" },
                { name: "reminders2hour" },
            ],
        },
        transport: {
            load: {
                url: "/storage/data/calendar-data.json",
            },
            sync: {
                url: "http://127.0.0.1:8000/api/save-calendar-data", // Sample save URL
            },
        },
        autoLoad: true,
        autoSync: true, // Automatically sync changes to the server
    },

I just want to understand how to store some additional boolean fields...

Last edited by dansmithcreates on Thu Jan 09, 2025 5:48 pm, edited 1 time in total.

Post by marcio »

Hey dansmithcreates,

Thanks for reaching out.

You can create a custom model with the new properties, and then use that model in your eventStore.

export default class Event extends EventModel {

static $name = 'Event';

static get fields() {
    return [{
        name : 'reminders5min',
        type : 'boolean'
    },
    {
        name : 'reminders15min',
        type : 'boolean'
    },
    {
        name : 'reminders30min',
        type : 'boolean'
    },
    {
        name : 'reminders55min',
        type : 'boolean'
    },
    {
        name : 'reminders1hour',
        type : 'boolean'
    },
    {
        name : 'reminders2hour',
        type : 'boolean'
    },];
}
}

// Then you your eventStore config

eventStore : {
       modelClass : Event
}

https://bryntum.com/products/calendar/docs/api/Core/data/Model#defining-fields
https://bryntum.com/products/calendar/docs/api/Scheduler/data/EventStore#config-modelClass

Best regards,
Márcio

How to ask for help? Please read our Support Policy


Post by dansmithcreates »

is that in its own file, and imported into CalendarConfig.ts? (the props file?)

Type 'typeof Event' is missing the following properties from type 'typeof EventModel': isEventModel, isEventModelMixin, isRecurringTimeSpan, isTimeSpan, and 18 more.

I am looking at the example at listview/src/lib/AppEventModel.ts

am only sort of getting this.. I think the props file vs just declaring things in a Calendar.vue file is throwing me off.


Post by marcio »

Hey,

It could be, but I'm sharing what your CalendarConfig would look like for that configuration (if you're defining the custom model inside the same file)

import { EventModel } from '@bryntum/calendar';
import { type BryntumCalendarProps } from '@bryntum/calendar-vue-3';

class Event extends EventModel {
    static $name = 'Event';

static get fields() {
    return [{
        name : 'reminders5min',
        type : 'boolean'
    },
    {
        name : 'reminders15min',
        type : 'boolean'
    },
    {
        name : 'reminders30min',
        type : 'boolean'
    },
    {
        name : 'reminders55min',
        type : 'boolean'
    },
    {
        name : 'reminders1hour',
        type : 'boolean'
    },
    {
        name : 'reminders2hour',
        type : 'boolean'
    }];
}
}

export const calendarProps : BryntumCalendarProps = {
    // Start life looking at this date
    date : new Date(2024, 7, 11),

// CrudManager arranges loading and syncing of data in JSON form from/to a web service
crudManager : {
    eventStore : {
        modelClass : Event
    },
    transport : {
        load : {
            url : 'data/data.json'
        }
    },
    autoLoad : true
},
};

Best regards,
Márcio

How to ask for help? Please read our Support Policy


Post by dansmithcreates »

I have appended the config file. When I click on a button, it is not finding eventRecord
When I go to save or sync, it is not finding the eventStore (pack.eventStore)

I've tried to incorporate your class (calling it ReminderEvent)

import { EventModel } from "@bryntum/calendar";
import { type BryntumCalendarProps } from "@bryntum/calendar-vue-3";
import { ref } from "vue";

const buttonClasses = ref({
    "5 Min": "button-5m",
    "15 Min": "button-15m",
    "30 Min": "button-30m",
    "45 Min": "button-45m",
    "1 HR": "button-1h",
    "2 HR": "button-2h",
});

// export default
class ReminderEvent extends EventModel {
    static $name = "ReminderEvent";

static get fields() {
    return [
        {
            name: "reminders5min",
            type: "boolean",
            default: true,
        },
        {
            name: "reminders15min",
            type: "boolean",
            default: true,
        },
        {
            name: "reminders30min",
            type: "boolean",
            default: true,
        },
        {
            name: "reminders55min",
            type: "boolean",
            default: true,
        },
        {
            name: "reminders1hour",
            type: "boolean",
            default: true,
        },
        {
            name: "reminders2hour",
            type: "boolean",
            default: true,
        },
    ];
}
}

function onReminderToggle({ source, pressed }) {
    const now = new Date();

console.log(source.owner);
console.log(source.owner.eventRecord); // it is not finding the event record
const buttonElement = source.element;

// Get the button's text
const identifier = source.text;
console.log("identifier", identifier);

// Retrieve the class from buttonClasses
const buttonClass = buttonClasses.value[identifier] || "";

// Toggle the class based on the pressed state
if (pressed && buttonClass) {
    buttonElement.classList.add(buttonClass);
    console.log("button on");
} else {
    if (buttonClass) {
        buttonElement.classList.remove(buttonClass);
    }
    console.log("button off");
}

// Set the reminder field on the event record
const eventRecord = source.owner.eventRecord;

console.log(eventRecord);
if (eventRecord) {
    const reminderField = `reminders${identifier
        .replace(" ", "")
        .toLowerCase()}`;
    eventRecord.set(reminderField, pressed);
}

console.log(buttonElement.classList);
console.log("Reminder toggled", source.text, "pressed:", pressed);
}

function onBeforeSync({ pack }) {
    console.log("onBeforeSync", pack);
    const eventStore = pack.eventStore;
    console.log(eventStore);
    eventStore.forEach((record) => {
        record.set("reminders5min", record.reminders5min || false);
        record.set("reminders15min", record.reminders15min || false);
        record.set("reminders30min", record.reminders30min || false);
        record.set("reminders45min", record.reminders45min || false);
        record.set("reminders1hour", record.reminders1hour || false);
        record.set("reminders2hour", record.reminders2hour || false);
    });

console.log(eventStore);
}

export const calendarProps: BryntumCalendarProps = {
    // Start life looking at this date
    date: new Date(2024, 7, 1),

sidebar: {
    items: {
        datePicker: {
            // highlight the selected cell's week row
            highlightSelectedWeek: true,
        },
    },
},

mode: "month",

eventEditFeature: {
    items: {
        details: {
            type: "panel",
        },
        editRecurrenceButton: {
            cls: "togbutton",
        },
        resourceField: null,

        reminderGroup: {
            type: "buttongroup",
            weight: 2700,

            name: "reminderGroup",
            title: "reminderGroup",
            cls: "togbutton",

            items: [
                {
                    type: "label",
                    text: "Reminders",
                    cls: "reminder-label",
                },
                {
                    type: "button",
                    name: "reminders5Min",
                    toggleable: true,
                    text: "5 Min",
                    toggled: false,
                    cls: buttonClasses.value["5m"],
                    onToggle: onReminderToggle,
                },

                {
                    type: "button",
                    name: "reminders15Min",
                    // pressed: true,
                    toggleable: true,
                    text: "15 Min",
                    toggled: false,
                    onToggle: onReminderToggle,
                },

                {
                    type: "button",
                    // pressed: true,
                    name: "reminders30Min",
                    toggleable: true,
                    text: "30 Min",
                    toggled: false,
                    onToggle: onReminderToggle,
                },
            ],
        },

        reminderGroup2: {
            type: "buttongroup",
            weight: 2900,

            name: "reminderGroup2",
            title: "reminderGroup2",
            cls: "togbutton",

            items: [
                {
                    type: "label",
                    text: "          ",
                    cls: "reminder-label",
                },
                {
                    type: "button",
                    toggleable: true,
                    name: "reminders45Min",
                    text: "45 Min",
                    toggled: false,
                    onToggle: onReminderToggle,
                },

                {
                    type: "button",
                    name: "reminders1hour",
                    toggleable: true,
                    text: "1 HR",
                    toggled: false,
                    onToggle: onReminderToggle,
                },

                {
                    type: "button",
                    name: "reminders2hour",
                    toggleable: true,
                    text: "2 HR",
                    toggled: false,
                    onToggle: onReminderToggle,
                },
            ],
        },
    },
},

modes: {
    month: {
        showWeekColumn: false,
    },
},

// CrudManager arranges loading and syncing of data in JSON form from/to a web service
crudManager: {
    eventStore: {
        modelClass: ReminderEvent,
    },

    transport: {
        load: {
            url: "/storage/data/calendar-data.json",
        },
        sync: {
            url: "http://127.0.0.1:8000/api/save-calendar-data", // Sample save URL
            method: "POST", // HTTP method for saving data
        },
    },
    autoLoad: true,
    autoSync: true, // Automatically sync changes to the server
    listeners: {
        beforeSync: onBeforeSync,
    },
},

// Features named by the properties are included.
// An object is used to configure the feature.
eventTooltipFeature: {
    // Configuration options are passed on to the tooltip instance
    // We want the tooltip's left edge aligned to the right edge of the event if possible.
    align: "l-r",
},

};


Post by marcio »

Hey,

Thanks for sharing your configuration.

I assembled a demo with that, and I'm sharing here the result https://codepen.io/marciogurka/pen/dPbmXNY.

I have also adjusted the arrangement of button groups to align with the rest of the editor's content.

You need to access record from the EventEditor widget, and then you can go with the code.

https://bryntum.com/products/calendar/docs/api/Calendar/widget/EventEditor#config-record

Best regards,
Márcio

How to ask for help? Please read our Support Policy


Post by dansmithcreates »

In your example, I dont think you actually checked your own result...

Go look at the code in onBeforeSync()
eventStore is still undefined. You are trying to loop over something that does not exist.

Go look at the console log at that point. No sign of the reminder button fields....

pen-error.jpg
pen-error.jpg (94.36 KiB) Viewed 259 times

Post by marcio »

Hey,

Sorry, I got confused with the button group part and didn't check this part.

I just updated the demo with the correct code and correct behavior. https://codepen.io/marciogurka/pen/dPbmXNY.

Also, just a few notes related to the code, you don't need the following piece of code if you set the defaultValue of the model to false.
https://bryntum.com/products/calendar/docs/api/Core/data/field/DataField#config-defaultValue

 records.forEach((record) => {
    record.set(“reminders5min”, record.reminders5min || false);
    record.set(“reminders15min”, record.reminders15min || false);
    record.set(“reminders30min”, record.reminders30min || false);
    record.set(“reminders45min”, record.reminders45min || false);
    record.set(“reminders1hour”, record.reminders1hour || false);
    record.set(“reminders2hour”, record.reminders2hour || false);
  });

Also, you don't need to access the eventStore on beforeSync, because in that listener you'll have the data before being sent to the server, not the model or the store itself.

If you check the demo, you'll see that the buttons will be unchecked when creating a new event, and will be updated when the user changes the values of the button group.

If you need more clarification, please don't hesitate to contact us here.

Best regards,
Márcio

How to ask for help? Please read our Support Policy


Post by dansmithcreates »

thank you, will check


Post by Animal »

This seems like the perfect application for grid layout to get the reminder buttons to lay out like that: https://codepen.io/Animal-Nige/pen/KwPoOjp?editors=0110


Post Reply