Our powerful JS Calendar component


Post by SHQK »

I follow your demo and using renderer in EventTooltip for display some data,
And I have a selection in EventTooltip,
How can I handle event onChange() of this selection?

    eventTooltip = {
        align: 'b-t',
        minWidth: null,
        tools: {
            delete: null,
            edit: null
        },
        renderer: eventRecord =>  
`<table style="width:100%"> <tr> <select onChange = "myFunction()"> ${this.eventStatusList.map(status => (`<option>${status.name}</option>`) ).join('')} </select> </tr> <tr> <td><i class="b-fa b-fa-phone-alt" style="font-size: 15px; color: #2196f3"></i></td> <td>${eventRecord.eventRecord.phone}</td> </tr> <tr> <td><i class="b-fa b-fa-calendar" style="font-size: 15px; color: #2196f3"></i></td> <td>${eventRecord.eventRecord.data.service}</td> </tr> </table>` };

Post by mats »

Use the 'listeners' config of the tooltip and listen to https://bryntum.com/docs/scheduler/#Core/widget/Tooltip#event-paint event. In this listener, you can listen to element events:

paint : ({ source }) => {
    source.element.addEventListener('change', () => ... }
}

Post by Animal »

Probably the best way is to create a custom Tooltip class which extends the provided one, and has widgets in it which handle all that...

import EventTip from <...the Calendar package...>

class MyEventTooltip extends EventTip {
    static get $name() {
        return 'MyEventTooltip';
    }
    
static get type() { return 'myeventtooltip'; } static get configurable() { return { // Child widgets of the tooltip. // One combobox and two read-only fields. items : { status : { type : 'combo', items : [...generated status list...], onChange({ value }) { // handle changes here... } }, phone { type : 'displayfield' }, service : { type : 'displayfield' } } }; } renderer() { // This is a Container. The record's fields will be distributed to // any widgets with the same named reference. // So fields "status", "phone" and "service" will be set automatically. this.record = this.eventRecord; } } // Register this new tooltip type type with its Factory MyEventTooltip.initClass();

Then tell the eventTooltip Feature to use that type:

features : {
    eventTooltip : {
        tooltip : {
            // Tell the feature to use our own tooltip subclass instead of the default
            type : 'myeventtooltip'
        }
    }
}

Post by SHQK »

Hi Animal,
I got this error,
How can I fix this and how can I set value from "eventRecord" to MyEventTooltip's Field ( status, phone, service, .. )

Attachments
rendertooltip.png
rendertooltip.png (9.19 KiB) Viewed 1771 times

Post by Animal »

It is there: https://www.bryntum.com/docs/calendar/#Calendar/widget/EventTip#config-eventRecord

And the renderer in the base class uses it. Tale a look at its source code.


Post by Animal »

Maybe the @tags aren't quite right to create the typescript.

Try adding this above that config in the EventTip base class and rebuilding:

            /**
             * The event record for this tip to display
             * @member {Scheduler.model.EventModel} eventRecord
             */

So that the source looks like this:

Screenshot 2021-07-16 at 11.48.26.png
Screenshot 2021-07-16 at 11.48.26.png (47.67 KiB) Viewed 1767 times

Post by SHQK »

Hi Animal,
I'm trying to config follow your guide in "calendar.lite.umd.js" file, but it's not working


Post by Animal »

Maybe you also need to tell typescript about the new class with an @extends tag:

/**
 * @extends Calendar/widget/EventTip
 */
class MyEventTooltip extends EventTip {
...
}

Post by SHQK »

Animal wrote: Fri Jul 16, 2021 12:43 pm

Maybe you also need to tell typescript about the new class with an @extends tag:

/**
 * @extends Calendar/widget/EventTip
 */
class MyEventTooltip extends EventTip {
...
}

Hi Animal,
Sorry for late reply,
I'm using VSCode and this IDE suggest me as below to fix this issues

eventRecord: import("@bryntum/calendar/calendar.lite.umd.js").Model;

But I'm not sure it's is correct because I can not display data from eventRecord
May be I think we need find another way

Attachments
2021-07-19_09h28_16.png
2021-07-19_09h28_16.png (10.37 KiB) Viewed 1745 times

Post by Animal »

I'm not sure about that import syntax. That's some kind of library?

But the class you need is EventModel, not the Model base class.

But it looks like you have some custom fields in the data. So you should create your own specialized subclass for that:

import EventModel ...from bryntum however you do it...

class MyEventModel extends EventModel {
    // Define extra fields in our subclass in addition to the inherited ones from the Bryntum EventModel class
    static get fields() {
        return [{
            name : 'status',
            type : 'number'
        }, {
            name : 'phone',
            type : 'string'
        }, {
            name : 'service',
            type : 'string'
        }]
    }
}

Then use that class as the modelClass of the eventStore.

This is assuming the incoming data object uses the same names, "status", "phone" and "service" which is obviously a good way of designing your data loading. Fields can load from a different JSON property name, but it's more intuitive to keep them the same.

So with those fields loaded, you should be able to set a breakpoint in your renderer in your class

renderer() {
    // This is a Container. The record's fields will be distributed to
    // any widgets with the same named reference.
    // So fields "status", "phone" and "service" will be set automatically.
    this.record = this.eventRecord;
}

Step into that and keep stepping in

You should reach this method

    updateRecord(record) {
        /**
         * Fired before this container will load record values into its child fields. This is useful if you
         * want to modify the UI before data is loaded (e.g. set some input field to be readonly)
         * @event beforeSetRecord
         * @param {Core.widget.Container} source The container
         * @param {Core.data.Model} record The record
         */
        this.trigger('beforeSetRecord', { record });
        this.setValues(record, true, !this.$highlight);
    }
    

Step into setValues

That distributes fields by name into child widgets with the same ref.

So those items of your EventTip subclass will have refs "status", "phone" and "service"

That's how it should work.


Post Reply