EventDrag

Allows user to drag and drop events within the scheduler, to change startDate or resource assignment.

Event drag
//<code-header>
fiddle.title = 'Event drag';
//</code-header>
const scheduler = new Scheduler({
    appendTo : targetElement,

    // makes scheduler as high as it needs to be to fit rows
    autoHeight : true,

    startDate : new Date(2018, 4, 6),
    endDate   : new Date(2018, 4, 13),

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

    resources : [
        { id : 1, name : 'Bernard' },
        { id : 2, name : 'Bianca' }
    ],

    events : [
        { id : 1, resourceId : 1, name : 'Drag me', startDate : '2018-05-06', endDate : '2018-05-07' },
        { id : 2, resourceId : 2, name : 'Or me', startDate : '2018-05-07', endDate : '2018-05-07' },
        { id : 3, resourceId : 2, name : 'But not me', startDate : '2018-05-08', endDate : '2018-05-10', draggable : false, eventColor : 'red' }
    ]
});

This feature is enabled by default

Customizing the drag drop tooltip

To show custom HTML in the tooltip, please see the tooltipTemplate config. Example:

features: {
    eventDrag : {
        // A minimal start date tooltip
        tooltipTemplate : ({ eventRecord, startDate }) => {
            return DateHelper.format(startDate, 'HH:mm');
        }
    }
}

Constraining the drag drop area

You can constrain how the dragged event is allowed to move by using the following configs

// Enable dragging + constrain drag to current resource
const scheduler = new Scheduler({
    features : {
        eventDrag : {
            constrainDragToResource : true
        }
    }
});

Drag drop events from outside

Dragging unplanned events from an external grid is a very popular use case. There are several demos showing you how to do this. Please see the Drag from grid demo and study the Drag from grid guide to learn more.

Drag drop events to outside target

You can also drag events outside the schedule area by setting constrainDragToTimeline to false. You should also either:

See this demo to see this in action.

Validating drag drop

It is easy to programmatically decide what is a valid drag drop operation. Use the validatorFn and return either true / false (optionally a message to show to the user).

features : {
    eventDrag : {
       validatorFn({ eventRecords, newResource }) {
           const task  = eventRecords[0],
                 valid = newResource.role === task.resource.role;

           return {
               valid   : newResource.role === task.resource.role,
               message : valid ? '' : 'Resource role does not match required role for this task'
           };
       }
    }
}

See this demo to see validation in action.

If you instead want to do a single validation upon drop, you can listen to beforeEventDropFinalize and set the valid flag on the context object provided.

  const scheduler = new Scheduler({
     listeners : {
         beforeEventDropFinalize({ context }) {
             const { eventRecords } = context;
             // Don't allow dropping events in the past
             context.valid = Date.now() <= eventRecords[0].startDate;
         }
     }
 });

Preventing drag of certain events

To prevent certain events from being dragged, you have two options. You can set draggable to false in your data, or you can listen for the beforeEventDrag event and return false to block the drag.

new Scheduler({
   listeners : {
       beforeEventDrag({ eventRecord }) {
           // Don't allow dragging events that have already started
           return Date.now() <= eventRecord.startDate;
       }
   }
})

Events that are selected, but not visually accessible, are not included in drag operations. This means that events in collapsed groups or filtered out resources are not dragged, even if they were selected prior to being collapsed or filtered out of visibility.

Configs

29

Common

disabledInstancePlugin
listenersEvents

Other

Set this to true to always copy the event on drag drop operation.

Set to true to only allow dragging events within the same resource.

Set to true to only allow dragging events to different resources, and disallow rescheduling by dragging.

A modifier key (CTRL, SHIFT, ALT, META) that when pressed will copy an event instead of moving it. Set to empty string to disable copying. Defaults to "CTRL" which is the Ctrl-key for Windows, and Meta-key for MacOS.

copyMode: auto | assignment | event= autoAlso a property

Event can be copied two ways: either by adding new assignment to an existing event ('assignment'), or by copying the event itself ('event'). 'auto' mode will pick 'event' for a single-assignment mode (when event has resourceId field) and 'assignment' mode otherwise.

A CSS selector specifying elements outside the scheduler element which are valid drop targets.

Set to true to only allow dragging in one direction (based on initial movement)

snapToPosition: function

A hook that allows manipulating the position the drag proxy snaps to. Manipulate the snapTo property to alter snap position.

const scheduler = new Scheduler({
    features : {
        eventDrag : {
            snapToPosition({ eventRecord, snapTo }) {
                if (eventRecord.late) {
                    snapTo.x = 400;
                }
            }
        }
    }
});
ParameterTypeDescription
contextObject
context.assignmentRecordAssignmentModel

Dragged assignment

context.eventRecordEventModel

Dragged event

context.resourceRecordResourceModel

Currently over this resource

context.startDateDate

Start date for current position

context.endDateDate

End date for current position

context.snapToObject
context.snapTo.xNumber

X to snap to

context.snapTo.yNumber

Y to snap to

Returns: void
snapToResource: Boolean | Object= trueAlso a property

Defaults to true, which snaps events to resources while dragging, i.e. vertical row snap in horizontal mode and vice versa. Requires Scheduler to be configured to snap to have any effect:

const scheduler = new Scheduler({
    ...
    // Snap to time & resource
    snap : true
});

If you want to customize the number of pixels from the dragged event that will trigger the snapping behavior to the new resource, you can set the threshold property:

const scheduler = new Scheduler({
    ...
    snap     : true,
    features : {
        eventDrag : {
            // Customized snap threshold
            snapToResource : {
                threshold : 30
            }
        }
    },
    ...
});
ParameterTypeDescription
thresholdNumber

Amount of pixels from dragged event to the edge of new resource that will trigger the snapping behaviour to the new resource.

tooltipTemplate: function

Template used to generate drag tooltip contents.

const scheduler = new Scheduler({
    features : {
        eventDrag : {
            tooltipTemplate({eventRecord, startText}) {
                return `${eventRecord.name}: ${startText}`
            }
        }
    }
});
ParameterTypeDescription
dataObject

Tooltip data

data.eventRecordEventModel
data.newResourceResourceModel

The new resource record

data.validBoolean

Currently over a valid drop target or not

data.startDateDate

New start date

data.endDateDate

New end date

Returns: String

When the host Scheduler is multiEventSelect: true then, there are two modes of dragging within the same Scheduler.

Non unified means that all selected events are dragged by the same number of resource rows.

Unified means that all selected events are collected together and dragged as one, and are all dropped on the same targeted resource row at the same targeted time.

validatorFn: function

An empty function by default, but provided so that you can perform custom validation on the item being dragged. This function is called during the drag and drop process and also after the drop is made. Return true if the new position is valid, false to prevent the drag.

features : {
    eventDrag : {
        validatorFn({ eventRecords, newResource }) {
            const
                task  = eventRecords[0],
                valid = newResource.role === task.resource.role;

            return {
                valid   : newResource.role === task.resource.role,
                message : valid ? '' : 'Resource role does not match required role for this task'
            };
        }
    }
}
ParameterTypeDescription
contextObject

A drag drop context object

context.startDateDate

New start date

context.endDateDate

New end date

context.assignmentRecordsAssignmentModel[]

Assignment records which were dragged

context.eventRecordsEventModel[]

Event records which were dragged

context.newResourceResourceModel

New resource record

context.targetEventRecordEventModel

Currently hovering this event record

eventEvent

The event object

Returns: Boolean | Object -

true if this validation passes, false if it does not.

Or an object with 2 properties: valid - Boolean true/false depending on validity, and message - String with a custom error message to display when invalid.

The this reference for the validatorFn

showTooltipDragBase
tipDragBase

Misc

clientInstancePlugin
localeClassLocalizable
localizableLocalizable

Properties

29

Common

disabledInstancePlugin

Class hierarchy

isEventDrag: Boolean= truereadonly
Identifies an object as an instance of EventDrag class, or subclass thereof.
isEventDrag: Boolean= truereadonlystatic
Identifies an object as an instance of EventDrag class, or subclass thereof.
isDragBaseDragBase
isEventsEvents
isInstancePluginInstancePlugin
isLocalizableLocalizable

Other

alwaysCopy: Boolean= falseAlso a config

Set this to true to always copy the event on drag drop operation.

Set to true to only allow dragging events within the same resource.

Set to true to only allow dragging events to different resources, and disallow rescheduling by dragging.

A modifier key (CTRL, SHIFT, ALT, META) that when pressed will copy an event instead of moving it. Set to empty string to disable copying. Defaults to "CTRL" which is the Ctrl-key for Windows, and Meta-key for MacOS.

copyMode: auto | assignment | event= autoAlso a config

Event can be copied two ways: either by adding new assignment to an existing event ('assignment'), or by copying the event itself ('event'). 'auto' mode will pick 'event' for a single-assignment mode (when event has resourceId field) and 'assignment' mode otherwise.

mode: move | copyreadonly

Mode of the current drag drop operation.

Set to true to only allow dragging in one direction (based on initial movement)

snapToResource: Boolean | Object= trueAlso a config

Defaults to true, which snaps events to resources while dragging, i.e. vertical row snap in horizontal mode and vice versa. Requires Scheduler to be configured to snap to have any effect:

const scheduler = new Scheduler({
    ...
    // Snap to time & resource
    snap : true
});

If you want to customize the number of pixels from the dragged event that will trigger the snapping behavior to the new resource, you can set the threshold property:

const scheduler = new Scheduler({
    ...
    snap     : true,
    features : {
        eventDrag : {
            // Customized snap threshold
            snapToResource : {
                threshold : 30
            }
        }
    },
    ...
});
ParameterTypeDescription
thresholdNumber

Amount of pixels from dragged event to the edge of new resource that will trigger the snapping behaviour to the new resource.

unifiedDrag: Boolean= falseAlso a config

When the host Scheduler is multiEventSelect: true then, there are two modes of dragging within the same Scheduler.

Non unified means that all selected events are dragged by the same number of resource rows.

Unified means that all selected events are collected together and dragged as one, and are all dropped on the same targeted resource row at the same targeted time.

isDraggingDragBase
showTooltipDragBase
tipDragBase

Lifecycle

configBase

Misc

clientInstancePlugin
localeHelperLocalizable
localeManagerLocalizable

Functions

30

Other

Provide your custom implementation of this to allow additional selected records to be dragged together with the original one.

ParameterTypeDescription
assignmentRecordAssignmentModel

The assignment about to be dragged

Returns: AssignmentModel[] -

An array of assignment records to drag together with the original

getTipHtmlDragBase
LstaticLocalizable
onEvents
relayAllEvents
triggerEvents
unEvents

Configuration

applyDefaultsstaticBase

Events

Lifecycle

destroystaticBase

Misc

doDisableInstancePlugin
initClassstaticBase
isOfTypeNamestaticBase
mixinstaticBase
optionalLstaticLocalizable

Events

14

Fired on the owning Scheduler after event drop

// Adding a listener using the "on" method
eventDrag.on('afterEventDrop', ({ source, assignmentRecords, eventRecords, valid, context, domEvent }) => {

});
ParameterTypeDescription
sourceScheduler
assignmentRecordsAssignmentModel[]
eventRecordsEventModel[]
validBoolean
contextObject
domEventMouseEvent

Browser event

Fired on the owning Scheduler before event dragging starts. Return false to prevent the action.

// Adding a listener using the "on" method
eventDrag.on('beforeEventDrag', ({ source, eventRecord, resourceRecord, eventRecords, assignmentRecords, domEvent }) => {

});
ParameterTypeDescription
sourceScheduler

Scheduler instance

eventRecordEventModel

Event record the drag starts from

resourceRecordResourceModel

Resource record the drag starts from

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

domEventMouseEvent

Browser event

This event is fired on the owning Scheduler after the event drag operation completes, but before changing any data. It allows implementer to use asynchronous validation/finalization by setting context.async = true in the listener, for example, to show a confirmation popup, make async data request etc. In such case, implementer need to call the context.finalize() method manually:

 scheduler.on('beforeeventdropfinalize', ({ context }) => {
     context.async = true;
     setTimeout(() => {
         // `true` to perform the drop, `false` to ignore it
         context.finalize(true);
     }, 1000);
 })

For synchronous one-time validation, simply set context.valid to true or false.

 scheduler.on('beforeeventdropfinalize', ({ context }) => {
     context.valid = false;
 })
// Adding a listener using the "on" method
eventDrag.on('beforeEventDropFinalize', ({ source, context, context.dropData, context.async, context.eventRecords, context.assignmentRecords, context.targetEventRecord, context.newResource, context.valid, context.finalize, domEvent }) => {

});
ParameterTypeDescription
sourceScheduler

Scheduler instance

contextObject
context.dropDataDropData

Information about the drop points for dragged events/assignments.

context.asyncBoolean

Set to true to not finalize the drag-drop operation immediately (e.g. to wait for user confirmation)

context.eventRecordsEventModel[]

Event records being dragged

context.assignmentRecordsAssignmentModel[]

Assignment records being dragged

context.targetEventRecordEventModel

The event record (if any) where the drop happened

context.newResourceResourceModel

Resource record for drop target

context.validBoolean

Set this to false to abort the drop immediately.

context.finalizefunction

Call this method after an async finalization flow, to finalize the drag-drop operation. This method accepts one argument: pass true to update records, or false to ignore changes

domEventMouseEvent

Browser event

Fired on the owning Scheduler when event is dragged

// Adding a listener using the "on" method
eventDrag.on('eventDrag', ({ source, eventRecords, assignmentRecords, startDate, endDate, resourceRecord, newResource, context, context.valid, domEvent }) => {

});
ParameterTypeDescription
sourceScheduler

Scheduler instance

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

startDateDate

Start date for the current location

endDateDate

End date for the current location

resourceRecordResourceModel

Resource record the drag started from

newResourceResourceModel

Resource at the current location

contextObject
context.validBoolean

Set this to false to signal that the current drop position is invalid.

domEventMouseEvent

Browser event

Fired on the owning Scheduler after an event drag operation has been aborted

// Adding a listener using the "on" method
eventDrag.on('eventDragAbort', ({ source, eventRecords, assignmentRecords, domEvent }) => {

});
ParameterTypeDescription
sourceScheduler

Scheduler instance

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

domEventMouseEvent

Browser event

Triggered when drag mode is changed, for example when copy key is pressed or released while dragging.

// Adding a listener using the "on" method
eventDrag.on('eventDragModeChange', ({ mode }) => {

});
ParameterTypeDescription
modeString

Drag mode, could be either 'move', 'copy', or 'auto'

Fired on the owning Scheduler after an event drag operation regardless of the operation being cancelled or not

// Adding a listener using the "on" method
eventDrag.on('eventDragReset', ({ source }) => {

});
ParameterTypeDescription
sourceScheduler

Scheduler instance

Fired on the owning Scheduler when event dragging starts

// Adding a listener using the "on" method
eventDrag.on('eventDragStart', ({ source, resourceRecord, eventRecords, assignmentRecords, domEvent }) => {

});
ParameterTypeDescription
sourceScheduler

Scheduler instance

resourceRecordResourceModel

Resource record the drag starts from

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

domEventMouseEvent

Browser event

Fired on the owning Scheduler when an event is dropped

// Adding a listener using the "on" method
eventDrag.on('eventDrop', ({ source, eventRecords, assignmentRecords, externalDropTarget, isCopy, context, context.targetEventRecord, context.newResource, domEvent }) => {

});
ParameterTypeDescription
sourceScheduler
eventRecordsEventModel[]
assignmentRecordsAssignmentModel[]
externalDropTargetHTMLElement

The HTML element dropped upon, if drop happened on a valid external drop target

isCopyBoolean
contextObject
context.targetEventRecordEventModel

Event record for drop target

context.newResourceResourceModel

Resource record for drop target

domEventMouseEvent

Browser event

catchAllEvents
destroyEvents
disableInstancePlugin
enableInstancePlugin

Event handlers

14

Called on the owning Scheduler after event drop

new EventDrag({
    onAfterEventDrop({ source, assignmentRecords, eventRecords, valid, context, domEvent }) {

    }
});
ParameterTypeDescription
sourceScheduler
assignmentRecordsAssignmentModel[]
eventRecordsEventModel[]
validBoolean
contextObject
domEventMouseEvent

Browser event

Called on the owning Scheduler before event dragging starts. Return false to prevent the action.

new EventDrag({
    onBeforeEventDrag({ source, eventRecord, resourceRecord, eventRecords, assignmentRecords, domEvent }) {

    }
});
ParameterTypeDescription
sourceScheduler

Scheduler instance

eventRecordEventModel

Event record the drag starts from

resourceRecordResourceModel

Resource record the drag starts from

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

domEventMouseEvent

Browser event

This event is called on the owning Scheduler after the event drag operation completes, but before changing any data. It allows implementer to use asynchronous validation/finalization by setting context.async = true in the listener, for example, to show a confirmation popup, make async data request etc. In such case, implementer need to call the context.finalize() method manually:

 scheduler.on('beforeeventdropfinalize', ({ context }) => {
     context.async = true;
     setTimeout(() => {
         // `true` to perform the drop, `false` to ignore it
         context.finalize(true);
     }, 1000);
 })

For synchronous one-time validation, simply set context.valid to true or false.

 scheduler.on('beforeeventdropfinalize', ({ context }) => {
     context.valid = false;
 })
new EventDrag({
    onBeforeEventDropFinalize({ source, context, domEvent }) {

    }
});
ParameterTypeDescription
sourceScheduler

Scheduler instance

contextObject
context.dropDataDropData

Information about the drop points for dragged events/assignments.

context.asyncBoolean

Set to true to not finalize the drag-drop operation immediately (e.g. to wait for user confirmation)

context.eventRecordsEventModel[]

Event records being dragged

context.assignmentRecordsAssignmentModel[]

Assignment records being dragged

context.targetEventRecordEventModel

The event record (if any) where the drop happened

context.newResourceResourceModel

Resource record for drop target

context.validBoolean

Set this to false to abort the drop immediately.

context.finalizefunction

Call this method after an async finalization flow, to finalize the drag-drop operation. This method accepts one argument: pass true to update records, or false to ignore changes

domEventMouseEvent

Browser event

Called on the owning Scheduler when event is dragged

new EventDrag({
    onEventDrag({ source, eventRecords, assignmentRecords, startDate, endDate, resourceRecord, newResource, context, domEvent }) {

    }
});
ParameterTypeDescription
sourceScheduler

Scheduler instance

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

startDateDate

Start date for the current location

endDateDate

End date for the current location

resourceRecordResourceModel

Resource record the drag started from

newResourceResourceModel

Resource at the current location

contextObject
context.validBoolean

Set this to false to signal that the current drop position is invalid.

domEventMouseEvent

Browser event

Called on the owning Scheduler after an event drag operation has been aborted

new EventDrag({
    onEventDragAbort({ source, eventRecords, assignmentRecords, domEvent }) {

    }
});
ParameterTypeDescription
sourceScheduler

Scheduler instance

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

domEventMouseEvent

Browser event

Called when drag mode is changed, for example when copy key is pressed or released while dragging.

new EventDrag({
    onEventDragModeChange({ mode }) {

    }
});
ParameterTypeDescription
modeString

Drag mode, could be either 'move', 'copy', or 'auto'

Called on the owning Scheduler after an event drag operation regardless of the operation being cancelled or not

new EventDrag({
    onEventDragReset({ source }) {

    }
});
ParameterTypeDescription
sourceScheduler

Scheduler instance

Called on the owning Scheduler when event dragging starts

new EventDrag({
    onEventDragStart({ source, resourceRecord, eventRecords, assignmentRecords, domEvent }) {

    }
});
ParameterTypeDescription
sourceScheduler

Scheduler instance

resourceRecordResourceModel

Resource record the drag starts from

eventRecordsEventModel[]

Event records being dragged

assignmentRecordsAssignmentModel[]

Assignment records being dragged

domEventMouseEvent

Browser event

Called on the owning Scheduler when an event is dropped

new EventDrag({
    onEventDrop({ source, eventRecords, assignmentRecords, externalDropTarget, isCopy, context, domEvent }) {

    }
});
ParameterTypeDescription
sourceScheduler
eventRecordsEventModel[]
assignmentRecordsAssignmentModel[]
externalDropTargetHTMLElement

The HTML element dropped upon, if drop happened on a valid external drop target

isCopyBoolean
contextObject
context.targetEventRecordEventModel

Event record for drop target

context.newResourceResourceModel

Resource record for drop target

domEventMouseEvent

Browser event

onDestroyEvents
onDisableInstancePlugin
onEnableInstancePlugin

Typedefs

4

Object with information about the drop point for a dragged assignment.

ParameterTypeDescription
assignmentRecordAssignmentModel

The assignment about to be dropped. Note, that in case if "copying" mode is enabled, this will still be the originally dragged assignment, not the copy (which will be created only during drag'n'drop finalization).

resourceRecordResourceModel

The new resource for the assignment. Note, that resource might belong to another project (in case of drag and drop between different scheduler instances).

Object with information about the drop points for the dragged events. It is used in the Scheduler's beforeEventDropFinalize event.

ParameterTypeDescription
eventsEventDropData[]

The array of drop points for every dragged event.

assignmentsAssignmentDropData[]

The array of drop points for every dragged assignment.

Object with information about the drop point for a single dragged event.

ParameterTypeDescription
eventRecordEventModel

The event about to be dropped. Note, that when "copying" mode is enabled, this will still be the originally dragged event, not the copy (which will be created only during drag'n'drop finalization).

startDateDate

The estimated start date of the event after drop. Note, that actual start date might be different because of the other features, affecting the scheduling, like dependencies and constraints.

endDateDate

The estimated end date of the event after drop. Note, that actual end date might be different because of the other features, affecting the scheduling, like dependencies and constraints.