Our pure JavaScript Scheduler component


Post by msan »

Hi team!

We've been using Bryntum Scheduler with great success so far in our project, but we're having a couple of weird cases we're not able to understand and hope you can shed some light into it.

Let's start with this one straight from the frameworks/angular/simpleeditor example, but with a little twist.

We've modified app.config.ts to have just these three resources:

const resources = [
    new ResourceModel({
        id       : 1,
        name     : 'Alfonso'
    }),
    new ResourceModel({
        id         : 2,
        name       : 'Pepe'
    }),
    new ResourceModel({
        id         : 3,
        name       : 'Manue'
    })
],

That works fine and displays them in the left margin of the scheduler. If we use this way of declaring events, as used in the example, events are being rendered and attached to their matching employees:

events = [
    {
        id         : 1,
        resourceId : 1,
        startDate  : new Date(2017, 0, 1, 10),
        endDate    : new Date(2017, 0, 1, 12),
        name       : 'First Task',
        iconCls    : 'b-fa b-fa-mouse-pointer'
    },
    {
        id         : 2,
        resourceId : 2,
        startDate  : new Date(2017, 0, 1, 12),
        endDate    : new Date(2017, 0, 1, 13, 30),
        name       : 'Lunch Break',
        iconCls    : 'b-fa b-fa-arrows-alt'
    }
]; // Works and attach events to resources

Image

That's great, but if we try to declare the same events as an array of EventModel types instead of plain objects:

events = [
    new EventModel({
        id         : 1,
        resourceId : 1,
        startDate  : new Date(2017, 0, 1, 10),
        endDate    : new Date(2017, 0, 1, 12),
        name       : 'First Task',
        iconCls    : 'b-fa b-fa-mouse-pointer'
    }),
    new EventModel({
        id         : 2,
        resourceId : 2,
        startDate  : new Date(2017, 0, 1, 12),
        endDate    : new Date(2017, 0, 1, 13, 30),
        name       : 'Lunch Break',
        iconCls    : 'b-fa b-fa-arrows-alt'
    })
]; // Doesn't attach events to resources

The events are not attached to the resources:

Image

Why is this happening? We couldn't find anything in the documentation that helps us understand why this second option is not displaying any event. Is there something we're doing wrong?

We've got a trickier issue related with this and we might open another post later, but we would love to understand this and get the basics right before digging into that ;)

Thanks a lot!
Miguel.


Post by alex.l »

Hi Miguel,

When you load static data, EvenModel instance is creating inside a store. The resourceId that you passed is trying to find corresponding resource in resourceStore and if it's there, an instance of AssignmentModel will be created in assignmentStore, and links to assignment and resource will be created in EventStore instance.
When you create EventStore instance before load to store, it's not possible to find any resource and assignment won't be created automatically. You need to use separated data for assignmentStore in that case.

Same for ResourceModel if it's created before loaded, it won't link assignments automatically without instructions in assignmentStore.

So, I suggest you to not create instances before load to store, or load assignments to assignmentStore.

https://bryntum.com/products/scheduler/docs/api/Scheduler/model/mixin/EventModelMixin#field-resourceId
https://bryntum.com/products/scheduler/docs/api/Scheduler/model/mixin/EventModelMixin#field-resources
https://bryntum.com/products/scheduler/docs/api/Scheduler/model/mixin/EventModelMixin#property-assignments
https://bryntum.com/products/scheduler/docs/api/Scheduler/data/AssignmentStore
https://bryntum.com/products/scheduler/docs/api/Scheduler/view/SchedulerBase#config-assignments

All the best,
Alex


Post by msan »

Thanks a lot for the reply and useful links Alex!

We've changed slightly the code so we don't create events in the store before the Scheduler is configured, but we're still unable to load the events to the resources in this way (as we would like to avoid interfering with the AssignmentStore, because that's supposed to be maintained and kept in sync by the Scheduler itself without any action required by us isn't it?)

We're still modifying the simpleeditor and now the HTML has this simple button to load the resources and events, so when we run the example it loads completely empty:

<!-- BryntumDemoHeader component is used for Bryntum example styling only and can be removed -->
<bryntum-demo-header></bryntum-demo-header>
<button (click)="assignEvents();">Click me</button>
<bryntum-scheduler
    #scheduler
    [startDate] = "schedulerConfig.startDate"
    [endDate] = "schedulerConfig.endDate"
    [viewPreset] = "schedulerConfig.viewPreset"
    [rowHeight] = "schedulerConfig.rowHeight"
    [barMargin] = "schedulerConfig.barMargin"
    [multiEventSelect] = "schedulerConfig.multiEventSelect"
    [resources] = "schedulerConfig.resources"
    [columns] = "schedulerConfig.columns"
    [events] = "schedulerConfig.events"
    [eventEditFeature] = "schedulerConfig.features.eventEdit"
    [simpleEventEditFeature] = "schedulerConfig.features.simpleEventEdit"
</bryntum-scheduler>

The config has been changed to:

export const schedulerConfig: Partial<SchedulerConfig> = {
    resourceStore : {
        modelClass : ResourceModel,
    },
    eventStore : {
        modelClass : EventModel,
    },
    startDate        : new Date(2017, 0, 1, 6),
    endDate          : new Date(2017, 0, 1, 20),
    viewPreset       : 'hourAndDay',
    rowHeight        : 50,
    barMargin        : 5,
    multiEventSelect : true,

columns : [
    { text : 'Name', field : 'name', width : 130 }
],

features : {
    eventEdit       : false,
    simpleEventEdit : true
}
};

And in the component .ts, we're creating the resources and events like this:

/**
 * App component script
 */
import { Component, ViewEncapsulation } from '@angular/core';
import { AssignmentModel, EventModel, ResourceModel } from '@bryntum/scheduler';
import { schedulerConfig } from './app.config';

@Component({
    selector      : 'app-root',
    templateUrl   : './app.component.html',
    styleUrls     : ['./app.component.scss'],
    encapsulation : ViewEncapsulation.None
})

export class AppComponent  {
    public schedulerConfig = schedulerConfig;

public assignEvents(){
    this.schedulerConfig.resources = [
            new ResourceModel({
                id       : 1,
                name     : 'Alfonso'
            }),
            new ResourceModel({
                id         : 2,
                name       : 'Pepe'
            }),
            new ResourceModel({
                id         : 3,
                name       : 'Manue'
            })
        ];

    this.schedulerConfig.events = [
        new EventModel({
            id         : 1,
            resourceId : 1,
            startDate  : new Date(2017, 0, 1, 10),
            endDate    : new Date(2017, 0, 1, 12),
            name       : 'First Task',
            iconCls    : 'b-fa b-fa-mouse-pointer'
        }),
        new EventModel({
            id         : 2,
            resourceId : 2,
            startDate  : new Date(2017, 0, 1, 12),
            endDate    : new Date(2017, 0, 1, 13, 30),
            name       : 'Lunch Break',
            iconCls    : 'b-fa b-fa-arrows-alt'
        })
    ]; // Doesn't attach events to resources
}
}

So this time, when we click the button, resources are created on the left side but no events show up in the Scheduler. How can we make it work with a similar approach?

Thanks a lot!


Post by alex.l »

public assignEvents(){
    this.schedulerConfig.resources 

At runtime you need to manipulate with scheduler instance and not config.

ngAfterViewInit(): void {
        this.scheduler = this.schedulerComponent.instance;
    }
    
// ... this.scheduler.resources = resources; this.scheduler.events = events;

All the best,
Alex


Post by alex.l »

export const schedulerConfig: Partial<SchedulerConfig> = {
    resourceStore : {
        modelClass : ResourceModel,
    },
    eventStore : {
        modelClass : EventModel,
    },

Btw, if you used default models, there is no need to specify them in configs

All the best,
Alex


Post by alex.l »

Actually after testing I see it doesn't work with your code. That's because new EventModel as I described above. new instance should be created in a store, in case of using resourceId approach. Or you can assign events after adding into the store.
https://bryntum.com/products/scheduler/docs/api/Scheduler/model/EventModel#function-assign

This code is working for me.

/**
 * App component script
 */
 import { AfterViewInit, OnInit, Component, ViewEncapsulation, ViewChild } from '@angular/core';
 import { Scheduler, AssignmentModel, EventModel, ResourceModel } from '@bryntum/scheduler';
 import { BryntumSchedulerComponent } from '@bryntum/scheduler-angular';
 import { schedulerConfig } from './app.config';
@Component({
    selector      : 'app-root',
    templateUrl   : './app.component.html',
    styleUrls     : ['./app.component.scss'],
    encapsulation : ViewEncapsulation.None
})

export class AppComponent implements AfterViewInit {

@ViewChild(BryntumSchedulerComponent, { static : true }) schedulerComponent: BryntumSchedulerComponent;

public schedulerConfig = schedulerConfig;
scheduler: Scheduler;

ngAfterViewInit(): void {
    this.scheduler = this.schedulerComponent.instance;
}

public assignEvents(){
    // @ts-ignore
    this.scheduler.resources = [
            {
                id       : 1,
                name     : 'Alfonso'
            },
            {
                id         : 2,
                name       : 'Pepe'
            },
            {
                id         : 3,
                name       : 'Manue'
            }
        ];
    // @ts-ignore
    this.scheduler.events = [
        {
            id         : 1,
            resourceId : 1,
            startDate  : new Date(2017, 0, 1, 10),
            endDate    : new Date(2017, 0, 1, 12),
            name       : 'First Task',
            iconCls    : 'b-fa b-fa-mouse-pointer'
        },
        {
            id         : 2,
            resourceId : 2,
            startDate  : new Date(2017, 0, 1, 12),
            endDate    : new Date(2017, 0, 1, 13, 30),
            name       : 'Lunch Break',
            iconCls    : 'b-fa b-fa-arrows-alt'
        }
    ]; 
}

}

All the best,
Alex


Post by msan »

Hi Alex!

I think I get it now, the key here is to set the scheduler config once and then get the whole scheduler instance, play around with their resources/events (being careful of linking them using their id fields), and the component would do the rest.

Thanks a lot for your example!

Regards,
Miguel.


Post Reply