Our pure JavaScript Scheduler component


Post by evindev »

Good morning,

I currently have this cell menu:

	this.rowSubMenu.forEach(el => {
            subMenuRow.push({
                text : el.descrizioneGate,
                codice: el.id,
                async onItem(event:any) {
                    component.isUpdating = true
                    let arrayOfChanges : {gate:IGateGantt | null,corsa:ICorseGantt,tipoGiorno:number}[] = []
                    let gateToAssign = await component.corseAssegnateResources.find(gate => this.codice === gate.id)
                    component.isUpdating = false
                    let rowEvents = await [...component.corseNonAssegnateEvents.filter(corsa => corsa.resourceId === event.id)]
                    await rowEvents.forEach(corsa => {
                        arrayOfChanges.push({gate:gateToAssign!,corsa:corsa,tipoGiorno:component.currentSetCorsa.codice})
                    });
                        
await component.ganttService.updateCorse(arrayOfChanges).pipe( switchMap((res: any) => { res.forEach((element: any) => { if (element.msg && element.msg !== '') { if(!element.saved){ component.messageService.add({ severity: 'error', summary: 'Errore di sovrapposizione', detail: element.msg }); }else{ component.messageService.add({ severity: 'warn', summary: 'Violazione vincoli', detail: element.msg }); } } }); if(res.some((el:any) => el.saved)){ component.messageService.add({ severity: 'success', summary: 'Successo', detail: 'Corsa associata con successo' }); } // return component.loadCorseScoperte(true) return component.loadGateCorseAssegnate() }), // switchMap((res: any) => { // return component.loadForkJoinCorse(res) // }) switchMap((res: ICorsaGate) => { component.schedulerAssegnatiContainer.instance.eventStore.data = res.resCorsa; component.corseAssegnateEvents = res.resCorsa component.schedulerAssegnatiContainer.instance.resourceStore.data = res.resGate.gates; component.corseAssegnateResources = res.resGate.gates component.schedulerAssegnatiContainer.resourceTimeRanges = res.resGate.timeRanges component.timeRanges = res.resGate.timeRanges return component.loadCorseScoperte(true) }) ).subscribe({ next: (results) => { component.schedulerNonAssegnatiContainer.instance.eventStore.data = results.corseScoperte; component.corseNonAssegnateEvents = results.corseScoperte // component.schedulerAssegnatiContainer.instance.eventStore.data = results.corse; // component.corseAssegnateEvents = results.corse component.isUpdating = false } }) }, }) }) this.nonAssegnateCellMenu = { items : { extraItem : { text : 'Assegna riga', icon : '', menu:subMenuRow }, removeRow : false, cut : false, copy : false, paste : false } } <bryntum-scheduler #schedulerNonAssegnatiContainer class="schedulerContainer" [viewPreset]="viewPreset" [columns]="columnsNonAssegnate" [startDate]="startDate" [endDate]="endDate" [resources]="corseNonAssegnateResources" [eventStore]="{data:corseNonAssegnateEvents}" [createEventOnDblClick]="false" [zoomOnTimeAxisDoubleClick]="false" [rowHeight]="40" [barMargin]="0" [multiEventSelect]="true" [allowOverlap]="false" [allowDropOnEventBar]="false" [zoomOnMouseWheel]="false" (onBeforeEventDropFinalize)="onEventDropFinalize($event)" [getDateConstraints]="getDateConstraints" (onEventClick)="onEventClick($event)" [eventTooltipFeature]="false" [scheduleTooltipFeature]="false" [scheduleMenuFeature]="false" [timeAxisHeaderMenuFeature]="false" [cellMenuFeature]="nonAssegnateCellMenu" [eventDragCreateFeature]="false" [eventEditFeature]="false" [eventResizeFeature]="false" [eventDragSelectFeature]="true" [filterBarFeature]="true" [columnRenameFeature]="false" [cellEditFeature]="false" [eventDragFeature]="{ constrainDragToTimeline : false, constrainDragToTimeSlot:true, }" [eventMenuFeature]="corseNonAssegnateEventMenu" ></bryntum-scheduler>

After some API calls, I should be able to reassign the submenu with different items. How do I reassign the items?

thanks


Post by mats »

This guide describes how to customize our context menus: https://bryntum.com/products/grid/docs/guide/Grid/customization/contextmenu

Use processItems to customize the items shown at each menu trigger.


Post by evindev »

Hi Mats,

I'm not sure if it's possible, but I tried using the processItems method inside the extraItems object, and it doesn't work. It seems that processItems only works for items:

this.nonAssegnateCellMenu = {
    items: {
        extraItems: {
            text: 'Assign row',
            icon: '',
            menu: subMenuRow,
        },
        removeRow: false,
        cut: false,
        copy: false,
        paste: false,
    }
}

The variable I'm dynamically rendering is "subMenuRow". The object is updated, but I can't reassign the object to the [cellMenuFeature] property of the scheduler.

I tried it this way:

this.schedulerNonAssegnatiContainer.cellMenuFeature = this.nonAssegnateCellMenu;

Post by mats »

processItems is a method you assign to the menu feature. Can you please share the code you tried?


Post by evindev »

Good morning Mats,

In the component, I have two schedulers. The cell menu of one of them has a subMenu where the items are the same array of resources from the other scheduler. Through this menu, I can assign all events of a row to a resource from the other scheduler and then make an API call to get the updated resources. In this case, if a resource has events, it will have a field "empty: false". At this point, in the subMenu, I need to hide all the elements of this array that have "empty: false".

Menu:

let subMenuRow:any[]=[]
let component = this

 this.rowSubMenu.forEach(el => {
            subMenuRow.push({
                text : el.descrizioneGate,
                codice: el.id,
                async onItem(event:any) {
                    component.isUpdating = true
                    let arrayOfChanges : {gate:IGateGantt | null,corsa:ICorseGantt,tipoGiorno:number}[] = []
                    let gateToAssign = await component.corseAssegnateResources.find(gate => this.codice === gate.id)
                    component.isUpdating = false
                    let rowEvents = await [...component.corseNonAssegnateEvents.filter(corsa => corsa.resourceId === event.id)]
                    await rowEvents.forEach(corsa => {
                        arrayOfChanges.push({gate:gateToAssign!,corsa:corsa,tipoGiorno:component.currentSetCorsa.codice})
                    });
                        
await component.ganttService.updateCorse(arrayOfChanges).pipe( switchMap((res: any) => { res.forEach((element: any) => { if (element.msg && element.msg !== '') { if(!element.saved){ component.messageService.add({ severity: 'error', summary: 'Errore di sovrapposizione', detail: element.msg }); }else{ component.messageService.add({ severity: 'warn', summary: 'Violazione vincoli', detail: element.msg }); } } }); if(res.some((el:any) => el.saved)){ component.messageService.add({ severity: 'success', summary: 'Successo', detail: 'Corsa associata con successo' }); } return component.loadGateCorseAssegnate() }), switchMap((res: ICorsaGate) => { component.schedulerAssegnatiContainer.instance.eventStore.data = res.resCorsa; component.corseAssegnateEvents = res.resCorsa component.schedulerAssegnatiContainer.instance.resourceStore.data = res.resGate.gates; component.corseAssegnateResources = res.resGate.gates component.schedulerAssegnatiContainer.resourceTimeRanges = res.resGate.timeRanges component.timeRanges = res.resGate.timeRanges return component.loadCorseScoperte(true) }) ).subscribe({ next: (results) => { component.schedulerNonAssegnatiContainer.instance.eventStore.data = results.corseScoperte; component.corseNonAssegnateEvents = results.corseScoperte component.isUpdating = false } }) }, }) }) this.nonAssegnateCellMenu = { items : { extraItems : { text : 'Assegna riga', icon : '', menu:subMenuRow, }, removeRow : false, cut : false, copy : false, paste : false, } } setTimeout(()=>{ //HERE I TRY TO REASSIGN THE CELLMENU //HERE subMenuRow is always updated this.schedulerNonAssegnatiContainer.cellMenuFeature.items.extraItems = subMenuRow console.log(this.schedulerNonAssegnatiContainer.cellMenuFeature.items.extraItems) this.schedulerNonAssegnatiContainer.instance.addPartner(this.schedulerAssegnatiContainer.instance) },100)

HTML

<bryntum-scheduler #schedulerNonAssegnatiContainer
                class="schedulerContainer"
                [viewPreset]="viewPreset"
                [columns]="columnsNonAssegnate"
                [startDate]="startDate"
                [endDate]="endDate"
                [resources]="corseNonAssegnateResources"
                [eventStore]="{data:corseNonAssegnateEvents}"
                [createEventOnDblClick]="false"
                [zoomOnTimeAxisDoubleClick]="false"
                [rowHeight]="40"
                [barMargin]="0"
                [multiEventSelect]="true"
                [allowOverlap]="false"
                [allowDropOnEventBar]="false"
                [zoomOnMouseWheel]="false"
                (onBeforeEventDropFinalize)="onEventDropFinalize($event)"
                [getDateConstraints]="getDateConstraints"
                (onEventClick)="onEventClick($event)"
                [eventTooltipFeature]="false"
                [scheduleTooltipFeature]="false"
                [scheduleMenuFeature]="false"
                [timeAxisHeaderMenuFeature]="false"
                [cellMenuFeature]="nonAssegnateCellMenu"
                [eventDragCreateFeature]="false"
                [eventEditFeature]="false"
                [eventResizeFeature]="false"
                [eventDragSelectFeature]="true"
                [filterBarFeature]="true"
                [columnRenameFeature]="false"
                [cellEditFeature]="false"
                [eventDragFeature]="{
                    constrainDragToTimeline : false,
                    constrainDragToTimeSlot:true,
                }"
                [eventMenuFeature]="corseNonAssegnateEventMenu"
            ></bryntum-scheduler>

Post by mats »

I don't see any use of processItems in your code..? Please see docs: https://bryntum.com/products/scheduler/docs/api/Grid/feature/CellMenu#config-processItems


Post by evindev »

Hi Mats,
if i do that nothing render. just the box of the main item but without text.

this.nonAssegnateCellMenu = {
            items : {
                extraItems : {
                    text : 'Assegna riga',
                    icon : '',
                    menu:subMenuRow,
                },
                removeRow : false,
                cut : false,
                copy : false,
                paste : false,
            },
            processItems(event:any) {
                //I Want to reassign submenuRow to extraItems at runtime
                event.items.extraItems = subMenuRow
            }
        }
        

Post by marcio »

Hey evindev,

In the snippet that you shared, you're replacing all the extraItems with only the menu, if you want to reassign subMenuRow only, you need to change to

 processItems(event:any) {
                //I Want to reassign submenuRow to extraItems at runtime
                event.items.extraItems.menu = subMenuRow
            }

Best regards,
Márcio


Post Reply