EventDrag
Allows user to drag and drop events within the scheduler, to change startDate or resource assignment.
//<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
- constrainDragToResource Resource fixed, only allowed to change start date
- constrainDragToTimeSlot Start date is fixed, only move between resources
- getDateConstraints A method on the Scheduler instance which lets you define the date range for the dragged event programmatically
// 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:
- provide a validatorFn to programmatically define if a drop location is valid or not
- configure a externalDropTargetSelector CSS selector to define where drops are allowed
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;
}
}
})
Configs
29
Configs
29Other
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.
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)
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;
}
}
}
}
});
| Parameter | Type | Description |
|---|---|---|
context | Object | |
context.assignmentRecord | AssignmentModel | Dragged assignment |
context.eventRecord | EventModel | Dragged event |
context.resourceRecord | ResourceModel | Currently over this resource |
context.startDate | Date | Start date for current position |
context.endDate | Date | End date for current position |
context.snapTo | Object | |
context.snapTo.x | Number | X to snap to |
context.snapTo.y | Number | Y to snap to |
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
}
}
},
...
});
| Parameter | Type | Description |
|---|---|---|
threshold | Number | Amount of pixels from dragged event to the edge of new resource that will trigger the snapping behaviour to the new resource. |
Template used to generate drag tooltip contents.
const scheduler = new Scheduler({
features : {
eventDrag : {
tooltipTemplate({eventRecord, startText}) {
return `${eventRecord.name}: ${startText}`
}
}
}
});
| Parameter | Type | Description |
|---|---|---|
data | Object | Tooltip data |
data.eventRecord | EventModel | |
data.newResource | ResourceModel | The new resource record |
data.valid | Boolean | Currently over a valid drop target or not |
data.startDate | Date | New start date |
data.endDate | Date | New end date |
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.
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'
};
}
}
}
| Parameter | Type | Description |
|---|---|---|
context | Object | A drag drop context object |
context.startDate | Date | New start date |
context.endDate | Date | New end date |
context.assignmentRecords | AssignmentModel[] | Assignment records which were dragged |
context.eventRecords | EventModel[] | Event records which were dragged |
context.newResource | ResourceModel | New resource record |
context.targetEventRecord | EventModel | Currently hovering this event record |
event | Event | The event 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
Misc
Properties
29
Properties
29Common
Class hierarchy
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.
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 of the current drag drop operation.
Set to true to only allow dragging in one direction (based on initial movement)
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
}
}
},
...
});
| Parameter | Type | Description |
|---|---|---|
threshold | Number | Amount of pixels from dragged event to the edge of new resource that will trigger the snapping behaviour to the new resource. |
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.
Functions
30
Functions
30Other
Provide your custom implementation of this to allow additional selected records to be dragged together with the original one.
| Parameter | Type | Description |
|---|---|---|
assignmentRecord | AssignmentModel | The assignment about to be dragged |
An array of assignment records to drag together with the original
Configuration
Events
Misc
Events
14
Events
14Fired on the owning Scheduler after event drop
// Adding a listener using the "on" method
eventDrag.on('afterEventDrop', ({ source, assignmentRecords, eventRecords, valid, context, domEvent }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | |
assignmentRecords | AssignmentModel[] | |
eventRecords | EventModel[] | |
valid | Boolean | |
context | Object | |
domEvent | MouseEvent | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
eventRecord | EventModel | Event record the drag starts from |
resourceRecord | ResourceModel | Resource record the drag starts from |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
domEvent | MouseEvent | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
context | Object | |
context.dropData | DropData | Information about the drop points for dragged events/assignments. |
context.async | Boolean | Set to |
context.eventRecords | EventModel[] | Event records being dragged |
context.assignmentRecords | AssignmentModel[] | Assignment records being dragged |
context.targetEventRecord | EventModel | The event record (if any) where the drop happened |
context.newResource | ResourceModel | Resource record for drop target |
context.valid | Boolean | Set this to |
context.finalize | function | Call this method after an async finalization flow, to finalize the drag-drop operation. This method accepts one
argument: pass |
domEvent | MouseEvent | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
startDate | Date | Start date for the current location |
endDate | Date | End date for the current location |
resourceRecord | ResourceModel | Resource record the drag started from |
newResource | ResourceModel | Resource at the current location |
context | Object | |
context.valid | Boolean | Set this to |
domEvent | MouseEvent | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
domEvent | MouseEvent | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
mode | String | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
resourceRecord | ResourceModel | Resource record the drag starts from |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
domEvent | MouseEvent | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | |
eventRecords | EventModel[] | |
assignmentRecords | AssignmentModel[] | |
externalDropTarget | HTMLElement | The HTML element dropped upon, if drop happened on a valid external drop target |
isCopy | Boolean | |
context | Object | |
context.targetEventRecord | EventModel | Event record for drop target |
context.newResource | ResourceModel | Resource record for drop target |
domEvent | MouseEvent | Browser event |
Event handlers
14
Event handlers
14Called on the owning Scheduler after event drop
new EventDrag({
onAfterEventDrop({ source, assignmentRecords, eventRecords, valid, context, domEvent }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | |
assignmentRecords | AssignmentModel[] | |
eventRecords | EventModel[] | |
valid | Boolean | |
context | Object | |
domEvent | MouseEvent | 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 }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
eventRecord | EventModel | Event record the drag starts from |
resourceRecord | ResourceModel | Resource record the drag starts from |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
domEvent | MouseEvent | 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 }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
context | Object | |
context.dropData | DropData | Information about the drop points for dragged events/assignments. |
context.async | Boolean | Set to |
context.eventRecords | EventModel[] | Event records being dragged |
context.assignmentRecords | AssignmentModel[] | Assignment records being dragged |
context.targetEventRecord | EventModel | The event record (if any) where the drop happened |
context.newResource | ResourceModel | Resource record for drop target |
context.valid | Boolean | Set this to |
context.finalize | function | Call this method after an async finalization flow, to finalize the drag-drop operation. This method accepts one
argument: pass |
domEvent | MouseEvent | Browser event |
Called on the owning Scheduler when event is dragged
new EventDrag({
onEventDrag({ source, eventRecords, assignmentRecords, startDate, endDate, resourceRecord, newResource, context, domEvent }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
startDate | Date | Start date for the current location |
endDate | Date | End date for the current location |
resourceRecord | ResourceModel | Resource record the drag started from |
newResource | ResourceModel | Resource at the current location |
context | Object | |
context.valid | Boolean | Set this to |
domEvent | MouseEvent | Browser event |
Called on the owning Scheduler after an event drag operation has been aborted
new EventDrag({
onEventDragAbort({ source, eventRecords, assignmentRecords, domEvent }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
domEvent | MouseEvent | Browser event |
Called when drag mode is changed, for example when copy key is pressed or released while dragging.
new EventDrag({
onEventDragModeChange({ mode }) {
}
});| Parameter | Type | Description |
|---|---|---|
mode | String | 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 }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
Called on the owning Scheduler when event dragging starts
new EventDrag({
onEventDragStart({ source, resourceRecord, eventRecords, assignmentRecords, domEvent }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | Scheduler instance |
resourceRecord | ResourceModel | Resource record the drag starts from |
eventRecords | EventModel[] | Event records being dragged |
assignmentRecords | AssignmentModel[] | Assignment records being dragged |
domEvent | MouseEvent | Browser event |
Called on the owning Scheduler when an event is dropped
new EventDrag({
onEventDrop({ source, eventRecords, assignmentRecords, externalDropTarget, isCopy, context, domEvent }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Scheduler | |
eventRecords | EventModel[] | |
assignmentRecords | AssignmentModel[] | |
externalDropTarget | HTMLElement | The HTML element dropped upon, if drop happened on a valid external drop target |
isCopy | Boolean | |
context | Object | |
context.targetEventRecord | EventModel | Event record for drop target |
context.newResource | ResourceModel | Resource record for drop target |
domEvent | MouseEvent | Browser event |
Typedefs
4
Typedefs
4Object with information about the drop point for a dragged assignment.
| Parameter | Type | Description |
|---|---|---|
assignmentRecord | AssignmentModel | 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). |
resourceRecord | ResourceModel | 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.
| Parameter | Type | Description |
|---|---|---|
events | EventDropData[] | The array of drop points for every dragged event. |
assignments | AssignmentDropData[] | The array of drop points for every dragged assignment. |
Object with information about the drop point for a single dragged event.
| Parameter | Type | Description |
|---|---|---|
eventRecord | EventModel | 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). |
startDate | Date | 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. |
endDate | Date | 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. |