Our powerful JS Calendar component


Post by Isilog »

Hello,

I try to create a custom Calendar's view for embedded a custom Scheduler component (yours but encapsulated inside another which contains our specific).

I do not find real example inside the documentation and other topics are not clear.

Firstly, I followed the documentation (https://www.bryntum.com/docs/calendar/guide/Calendar/gettingstarted/customview) but with compile error for "Calendar.Modes.register" which is not defined (after search, I find it exists but not defined in TypeScript).

error.PNG
error.PNG (88.37 KiB) Viewed 536 times

But after that, what do I need to do ?

The example "Custom rendering (https://bryntum.com/examples/calendar/custom-rendering/) show that the custom view need to extend "Grid.mixin(CalendarStores)" but another compiler error appear.

error2.PNG
error2.PNG (58.17 KiB) Viewed 536 times

In the topic viewtopic.php?p=74987 I have seen another example which extends "CalendarPanel" and another that extends "Grid".

For clarity, can you provide an interface that the custom view need to implement ?

Thanks


Post by mats »

Did you see the code of this demo? https://bryntum.com/examples/calendar/calendar-scheduler/

If you are only trying to add our Scheduler, this demo shows exactly what is required:

const calendar = new Calendar({
    appendTo : 'container',

// Start life looking at this date
date : new Date(2020, 9, 11),

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

// These will take precedence over the Scheduler's features.
features : {
    eventMenu : {
        items : {
            editEvent : {
                text   : 'Edit',
                weight : 100
            }
        }
    }
},

tbar : {
    items : {
        scale : {
            type    : 'slider',
            text    : 'Scale',
            min     : 25,
            max     : 100,
            value   : tickWidth,
            weight  : 650,
            width   : 100,
            onInput : ({ value }) => calendar.modes.timeline.tickSize = value
        }
    }
},

mode : 'timeline',

modes : {
    day : {
        dayStartTime : 7,
        dayEndTime   : 22
    },

    week : {
        dayStartTime : 7,
        dayEndTime   : 22
    },

    timeline : {
        type : 'scheduler',

        // Used by the Calendar's mode selector button
        displayName : 'Timeline',

        // Used by resourceInfo column to base src for image field:
        resourceImagePath : '../_shared/images/users/',

        // Change default event style for Scheduler to better match Calendars look
        eventStyle : 'calendar',

        columns : [
            { type : 'resourceInfo', field : 'name', text : 'Staff/Resource', width : 175 }
        ],

        features : {
            nonWorkingTime : true
        },

        workingTime : {
            fromHour : 7,
            toHour   : 22
        },

        // Uncomment to change the date range of the time axis
        // range : 'month',

        // Uncomment to change how much the next / previous buttons shift the time axis
        // stepUnit : 'day',

        viewPreset : {
            base : 'hourAndDay',
            tickWidth,

            headers : [{
                unit       : 'day',
                dateFormat : 'ddd MM/DD'
            }, {
                unit       : 'hour',
                dateFormat : 'h'
            }]
        },

        // Custom eventRenderer to match style used by Calendar
        eventRenderer({ eventRecord, renderData }) {
            if (eventRecord.isInterDay) {
                renderData.eventStyle = 'interday';
                return StringHelper.encodeHtml(eventRecord.name);
            }

            renderData.style = 'align-items: start';

            const
                { eventColor, iconCls } = renderData,
                noIcon                  = !iconCls?.length,
                isRecurring             = eventRecord.isRecurring || eventRecord.isOccurrence;

            return {
                class    : 'b-cal-event-body',
                children : [
                    {
                        class    : 'b-event-header',
                        children : [
                            {
                                class : 'b-event-time',
                                text  : DateHelper.format(eventRecord.startDate, 'LST')
                            },
                            isRecurring && {
                                tag   : 'i',
                                class : {
                                    'b-icon'                : 1,
                                    'b-fw-icon'             : 1,
                                    'b-cal-event-icon'      : !noIcon,
                                    'b-cal-recurrence-icon' : noIcon,
                                    'b-icon-recurring'      : noIcon,
                                    ...DomClassList.normalize(iconCls, 'object')
                                },
                                style : eventColor ? {
                                    color : eventColor
                                } : null
                            }
                        ]
                    }, {
                        class : 'b-cal-event-desc',
                        text  : eventRecord.name
                    }
                ]
            };
        }
    }
}
});

Post by Isilog »

Hello,

Yes, I have seen this example but sorry, it's for pure Javascript, not for an Angular component.

I have created a regular Angular component which extends/configures your Scheduler with some service dependency injections and other things. All it's working for this.

@Component({
    selector: 'isi-scheduler',
    templateUrl: './isi-scheduler.component.html',
    styleUrls: ['./isi-scheduler.component.css']
})
export class IsiSchedulerComponent implements AfterViewInit { //, OnDestroy

static type = "IsiSchedulerComponent"
scheduler: SchedulerPro;
public grid: Grid;
public eventStore: SchedulerEventStore | EventStore;

private _viewModel1: IsiSchedulerViewModel;
private _viewModel2: IsiSchedulerViewModel;

// @Input()
// infiniteScroll: boolean = false;

currentLanguage: string = 'en';

@Input() autoRescheduleTasks = false;
@Input() viewModelId: string;
@Input() dual: boolean;
@Input() dualShareBar: boolean;

@ViewChild('scheduler1', { static: true }) scheduler1Component: BryntumSchedulerProComponent;

private scheduler2Component: BryntumSchedulerProComponent;
@ViewChild('scheduler2', { static: false }) set content(child) {
    if (!child) return;
    this.scheduler2Component = child;
};

@ViewChild(BryntumGridComponent, { static: true }) gridComponent: BryntumGridComponent;

constructor(
    public router: Router,
    public route: ActivatedRoute,
    public store: Store<{ barMargin: { barMargin: number } }>,
    @Inject(I18NEXT_SERVICE) private i18NextService: ITranslationService,
    private taskCardRendererService: TaskCardRendererService,
    public schedulerViewModelService: IsiSchedulerViewModelService,
    private groupFeatureConfigService: IsiSchedulerGroupFeatureConfigService,
    public tbarConfigService: SchedulerTBarConfigService,
    public presetStoreService: SchedulerPresetStoreService,
    public projectService: SchedulerProjectService,
) {

}
...

I want to reuse my component and not redeclare/duplicate all scheduler configuration and all of these behaviours in another place. It's the first goal to do components.

With the same model, I have created another angular component which extends/configures your Calendar.
With this, I have created my custom view and registered it (after having added a "bad" any to the line to have compilation success) :

//Bad need to use any
(<any>Calendar).Modes.register('isischeduler', IsiSchedulerView);

@Component({
  selector: 'isi-calendar',
  templateUrl: './isi-calendar.component.html',
  styleUrls: ['./isi-calendar.component.scss']
})
export class IsiCalendarComponent implements AfterViewInit {

  @ViewChild(BryntumCalendarComponent) calendarComponent: BryntumCalendarComponent;

  private calendar: Calendar;
  private eventStore: EventStore;

  @Input() viewModelId: string;
  ...
 

What is the contract of the class "IsiSchedulerView" and what does it need to implement ?


Post by alex.l »

It doesn't really matter if it's pure JS or Angular. Our classes are cross-platformed and will incapsulate all the logic inside.
You just need to register JS class in modes, as you did according to code snippet, and use registered mode in calendar modes. That mode should be a JS class and not Angular component. We do not support Angular components as mode.

All the best,
Alex


Post Reply