The Scheduler events can be moved using drag and drop. This functionality is enabled by default.
Event handling
As soon as the user drops the event at the target position, two events are fired:
These events let you handle the server-side notification.
-
The
onEventMove
event is fired before the default action. -
The default action is set using the evenMoveHandling property. The default value is
"Update"
which means the event will be moved to the new location and the Scheduler UI will be updated. -
The
onEventMoved
event is fired after the default action.
You can use the onEventMove
event handler to perform additional checks and cancel the default action if needed:
-
ask the user for confirmation
-
check the server asynchronously to verify that the business rules are met
-
decide what action to perform, depending on the status of modifier keys
You can also forbid moving of of individual events using the onBeforeEventRender
event handler (see event customization):
-
completely disable moving
-
only allow moving in the vertical or horizontal direction (see limit event moving)
You can also perform additional actions in these event handlers that update related events:
Example: Ask for a confirmation using a modal dialog
This example uses DayPilot.Modal.confirm() to display a modal dialog that asks for confirmation. If you cancel the confirmation dialog, the event will not be moved - the default action is canceled using args.preventDefault()
method.
The DayPilot.Modal.confirm()
method is asynchronous (it returns a Promise
). That means it is necessary to switch to the async mode using args.async = true
(otherwise the delayed args.preventDefault()
call would be ignored).
You can replace the basic DayPilot.Modal.confirm()
dialog with a custom dialog created using DayPilot.Modal.form().
onEventMove: async (args) => {
args.async = true;
const modal = await DayPilot.Modal.confirm("Do you really want to move this event?");
if (modal.canceled) {
args.preventDefault();
}
args.loaded();
}
Example: Display a message when moving is completed
In the onEventMoved
event handler, you can display a confirmation using the built-in message bar.
onEventMoved: (args) => {
dp.message("Moved: " + args.e.text());
}
Drag handle
Events can be dragged by pressing a mouse button anywhere in the event (except for the resize margins on the left and on the right which activate drag and drop event resizing).
You can disable the built-in mechanism and use a custom drag handle.
Touch devices
Event moving is also supported on touch devices.
In order to activate event moving, use the tap-and-hold gesture. The timeout needed for event moving activations can be adjusted using tapAndHoldTimeout property. By default, it uses the value of 300 (ms).
To provide a visual guide on touch devices, you can also create a custom drag handle using active areas. This way you can add an icon that will activate an event moving on simple tap (without the need to hold the finger for the specified time).
Real-time moving customization
Once the moving mode is activated, the Scheduler will display a shadow at the target location:
You can customize the moving using the onEventMoving
event handler. You can use this event to to implement the following features:
-
customize the shadow appearance (CSS, HTML)
-
dynamically calculate whether the target position is allowed
-
adjust the target position and duration
-
display custom labels next to the target shadow
You also can define a specific date range for each event, indicating the time frame within which the event can be rescheduled or moved.
While being dragged, the source event will be marked with *_scheduler_defaut_event_source
CSS class. By default, it makes the source event semi-transparent using opacity
CSS style.
Target position indicators
The Scheduler can display in-line indicators that display the current start/end date of the shadow.
Moving multiple events at once
It is possible to move multiple events at once:
-
you can join several events so they will always be moved together (demo)
-
you can select multiple events and move them at once
See also JavaScript Scheduler: Copy Multiple Events.
Dragging events from an external source
You can drag external items to the Scheduler:
-
You can have a list of unscheduled events/tasks that can be moved to the Scheduler grid (see external drag and drop).
-
You can move external items into events (tutorial: Events as drag and drop target).
-
It is also possible to drag items from other applications/desktop (tutorial: Dragging files and other items from desktop).
Copy events using drag and drop
With a few tweaks, it is possible to use this feature to make copies of existing events instead of moving them.
Skip non-business hours/days
The Scheduler can hide non-business hours from the timeline and you can configure event moving to extend the event duration accordingly (to exclude the hidden hours).
Undo/Redo
You can extend the functionality to save a history of changes that will let users perform undo and redo actions.
JavaScript Scheduler
This JavaScript Scheduler example uses onEventMove
to update the event position using an HTTP call to an API endpoint. It waits for the response, updates the UI (the default action is set to "Update") and displays a confirmation message using onEventMoved
.
<div id="dp"></div>
<script type="application/javascript">
const dp = new DayPilot.Scheduler("dp", {
eventMoveHandling: "Update",
onEventMove: async (args) => {
args.async = true;
const id = args.e.data.id;
const params = {
start: args.newStart,
end: args.newEnd,
resource: args.newResource
};
const {data} = await DayPilot.Http.put(`/api/events/${id}`, params);
args.loaded();
},
onEventMoved: args => {
dp.message("Event sucessfuly moved.");
},
// ...
});
dp.init();
</script>
Angular Scheduler
In the Angular Scheduler component, you can specify the event handlers using the config
object.
This example submits the event position change using a PUT HTTP call to /api/events/{id}
in onEventMove
. The processing is switched to asynchronous mode using args.async = true
. That will postpone further processing (including the default action) until args.loaded()
is called. In onEventMoved
, the Scheduler displays a confirmation message using the built-in message bar.
import {Component, ViewChild, AfterViewInit} from '@angular/core';
import {DayPilot, DayPilotSchedulerComponent} from 'daypilot-pro-angular';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'scheduler-component',
template: `<daypilot-scheduler [config]="config" [events]="events" #scheduler></daypilot-scheduler>`,
styles: [``]
})
export class SchedulerComponent implements AfterViewInit {
@ViewChild('scheduler')
scheduler!: DayPilotSchedulerComponent;
events: DayPilot.EventData[] = [];
config: DayPilot.SchedulerConfig = {
eventMoveHandling: "Update",
onEventMove: (args) => {
args.async = true;
const url = `/api/events/${args.e.data.id}`;
this.http.put(url, args.e.data).subscribe(response => {
args.loaded();
}, error => {
args.control.message("Error updating event on server: " + error);
});
},
onEventMoved: (args) => {
args.control.message("Event updated on server: " + args.e.text());
},
// ...
};
constructor(private http: HttpClient) {}
ngAfterViewInit(): void {
this.http.get('/api/resources').subscribe(result => {
this.config.resources = result;
});
const from = this.scheduler.control.visibleStart();
const to = this.scheduler.control.visibleEnd();
this.http.get(`/api/events?start=${from}&end=${to}`).subscribe(result => {
this.events = result;
});
}
}
ASP.NET WebForms
Drag and drop event moving is disabled by default.
It can be enabled using EventMoveHandling property. It has to be set to one of the following values:
-
CallBack
-
PostBack
-
Notify
-
JavaScript
PostBack event handling type will fire a server-side event handler (EventMove) using a PostBack (or partial AJAX PostBack if the scheduler is inside an UpdatePanel).
CallBack event handling type will fire a server-side event handler (EventMove) using an AJAX callback. CallBack is much faster than PostBack (and partial PostBack).
Notify event handling type will update the scheduler on the client immediately and then notify the server (EventMove) using an AJAX callback. Notify is much faster than CallBack.
JavaScript event handling will fire the JavaScript code specified in EventMoveJavaScript.
-
The following variables are available to the client-side handler: e, newStart, newEnd, newResource, external, ctrl, shift (see DayPilot.Scheduler.onEventMove)
-
The client side handler can call the server-side handler using eventMoveCallBack() and eventMovePostBack() method
Server-Side Handler
<DayPilot:DayPilotScheduler runat="server" id="DayPilotScheduler1"
...
EventMoveHandling = "CallBack"
OnEventMove="DayPilotScheduler1_EventMove"
/>
Example EventMove handler:
protected void DayPilotScheduler1_EventMove(object sender, DayPilot.Web.Ui.Events.EventMoveEventArgs e)
{
// update the database
// ...
// reload events and refresh the scheduler on the client side
DayPilotScheduler1.DataSource = LoadData(); // your method
DayPilotScheduler1.DataBind();
DayPilotScheduler1.UpdateWithMessage("Event moved.");
}
If any changes are made to the event data set (which is the typical case), it is necessary to redraw the event set on the client side using an Update() or UpdateWithMessage() call.
Asking for Confirmation
The server-side event handler will only be fired if the user confirms the action:
<DayPilot:DayPilotScheduler runat="server" id="DayPilotScheduler1"
...
ClientObjectName="dps"
EventMoveHandling = "JavaScript"
EventMoveJavaScript="if (confirm('Do you really want to move this event?')) { dps.eventMoveCallBack(e, newStart, newEnd, newResource); } "
OnEventMove="DayPilotScheduler1_EventMove"
/>
ASP.NET MVC
Drag & drop event moving is disabled by default.
It can be enabled using EventMoveHandling property. It has to be set to one of the following values:
-
CallBack
-
Notify
-
JavaScript
CallBack event handling will fire a server-side event handler (OnEventMove) using an AJAX callback.
Notify event handling type will update the scheduler on the client immediately and then notify the server using an AJAX call. Notify is much faster than CallBack.
JavaScript event handling will fire the JavaScript code specified in EventMoveJavaScript.
-
The following variables are available to the client-side handler: e, newStart, newEnd, newResource, external, ctrl, shift (see DayPilot.Scheduler.onEventMove)
-
The client side handler can call the server-side handler using eventMoveCallBack() method
Server-Side Handler
@Html.DayPilotScheduler("dps", new DayPilotSchedulerConfig {
BackendUrl = ResolveUrl("~/Scheduler/Backend"),
...
EventMoveHandling = EventMoveHandlingType.CallBack
})
The EventMove event can be handled by overriding the OnEventMove method in the DayPilotScheduler implementing class:
protected override void OnEventMove(EventMoveArgs e)
{
new EventManager(Controller).EventMove(e.Id, e.NewStart, e.NewEnd, e.NewResource);
Update();
}
protected override void OnFinish()
{
// only load the data if an update was requested by an Update() call
if (UpdateType == CallBackUpdateType.None)
{
return;
}
Events = new EventManager(Controller).FilteredData(StartDate, EndDate, (string)ClientState["filter"]).AsEnumerable();
DataStartField = "start";
DataEndField = "end";
DataTextField = "text";
DataIdField = "id";
DataResourceField = "resource";
}
If any changes are made to the event data set (which is the typical case), it is necessary to redraw the event set on the client side using an Update() call.