Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Creating Tasks from Calendar Interactions in FSM Dispatcher Workspace

Ramya V
Kilo Sage
Kilo Sage

This article explains how to enable task creation directly from the calendar grid in FSM Dispatcher Workspace using Drag End, Grid Click, and Grid Double-Click events. The goal is to provide an Outlook-like scheduling experience for dispatchers.

Important Note

This implementation works best when a single assignment group is used for wm_agents. The same approach can be extended to any page that uses the Calendar Component, depending on your requirements.

1. Calendar Event Types & Payloads

The Calendar Component emits different events based on user actions. These events supply the necessary information to open a modal and prefill Work Order Task details automatically.

1.1 Drag End for New Event

Triggered when the user drags on the calendar to create a time slot.

Payload:

- newStartMS: Start time in UTC milliseconds

- newEndMS: End time in UTC milliseconds

- group: Technician/agent row identifier

1.2 Event Clicked

Triggered when the user selects a calendar grid.

Payload:

- event: Selected event object

- chunkStartDateMS: Start time of selected chunk

- chunkEndDateMS: End time of selected chunk

1.3 Event Double Clicked

Triggered when the user double-clicks on the calendar grid to create a new time slot.

Payload:

- newStartMoment / newEndMoment (Moment objects)

- newStartMS / newEndMS (UTC milliseconds)

- group (Technician row identifier)

2. Enabling New Event Creation

By default, the client state `EnableCalendarNewEvent` blocks task creation from the calendar.

OOTB Navigation:

Calendar component → Scroll to bottom → "Enable new calendar click" → Edit (pencil icon)

RamyaV_42-1763987587374.png

 

When you click the pencil icon, the system shows that Enable new calendar click = true, which allows calendar-based event creation.

 

RamyaV_43-1763987587374.png

To enable the functionality:

  1. Open Calendar Component → Add Event Mapping
  2. Add the following mappings:

   - Drag End for New Event

   - Grid Clicked for New Event

   - Grid Double-Clicked

  1. Add these handlers to each mapping:

   - Client Script

   - Open/Close Modal Dialog

3. Creating the Custom Modal Dialog

Create a modal dialog to capture:

- Assigned technician

- Work order reference

- Description

- Start and end time

RamyaV_44-1763987587376.png

 

RamyaV_45-1763987587380.png

 

 

A client state variable named payload stores the technician and time information from the calendar event.

RamyaV_46-1763987587384.png

Example: Assigned To field binding

Bind the modal’s “Assigned To” field to:

@STate.payload.user

Each modal field (input/select) binds to a specific property inside payload, depending on the field type.

Updating the Client State

To update individual field values, add an Event Handler → Script on the input component:

Example Script:

/**
*  {params} params
*  {api} params.api
*  {any} params.event
*/
function evaluateEvent({api, event}) {
    return {
        propName: "payload",
        value: {
            ...api.state.payload,      // keep existing keys
            user: event.payload.value|| null  // update only `user`
        }
    };
}

This updates only the user field while preserving all other payload values.

Picture 1.png    Picture 2.png    

Picture 3.png

4. Client Script to Capture Calendar Interaction

To configure the calendar behavior:

Navigate to:
UI Builder → Page → Client Scripts → Add Script

Use the following script to extract the selected agent ID, round time to 15-minute intervals (Dispatcher Workspace default), and update the payload (client-state parameter).

RamyaV_50-1763987587396.png

Client Script

function handler({ api, event }) {
    const drag = event.payload;
    const userId = drag.group?.split("_")[1] || null;
    const rawStart = drag.newStartMoment;
    const rawEnd   = drag.newEndMoment;
    const roundTo15 = m => {
        const minutes = m.minutes();
        const rem = minutes % 15;
        if (rem !== 0 || m.seconds() !== 0 || m.milliseconds() !== 0) {
            m.add(15 - rem, "minutes");
            m.startOf("minute");
        }
        return m;
    };
    const roundedStart = roundTo15(rawStart.clone());
    const roundedEnd   = roundTo15(rawEnd.clone());
    const finalStart = roundedStart.format("YYYY-MM-DD HH:mm:ss");
    const finalEnd   = roundedEnd.format("YYYY-MM-DD HH:mm:ss");

    api.setState("payload", {
        user: userId,
        start: finalStart,
        end: finalEnd
    });
}

 

5. Creating the Work Order Task

Dispatcher Workspace already includes a Create Record data resource.

Configure the Submit button (Event Handler → Create Record) and switch to Script Mode.

RamyaV_51-1763987587406.png

 

Use this script inside the Create Record Data Resource to create the wm_task:

Create Record Script

function evaluateEvent({api, event}) {

    const p = api.state.payload;
    var fields = '';
    const start = p.start;
    const end = p.end;
    let duration = "00:00:00";
    if (start && end && end > start) {
        const diff = (new Date(end) - new Date(start)) / 1000;
        const hh = String(Math.floor(diff / 3600)).padStart(2, "0");
        const mm = String(Math.floor((diff % 3600) / 60)).padStart(2, "0");
        const ss = String(Math.floor(diff % 60)).padStart(2, "0");
        duration = `${hh}:${mm}:${ss}`;
    }

    fields += "parent=" + p.workorder;
    fields += "^short_description=" + p.description;
    fields += "^assigned_to=" + p.user;
    fields += "^state=12";
    fields += "^expected_start=" + p.start;
    fields += "^estimated_work_duration=" + duration;
    return {

        table: "wm_task",
        templateFields: fields,
        useSetDisplayValue: null
    };
}

6. Wiring the Event Handlers

Drag End

Available OOTB in Calendar Component.

Grid Clicked / Grid Double-Clicked

Must be added using Add Event Mapping.

 

RamyaV_57-1763987662972.png

 

For each calendar interaction (Drag End, Grid Clicked, Grid Double-Clicked), add(using add handler):

- Client Script handler

- Open/Close Modal Dialog handler

 

    Picture 4.png.   Picture 5.png

 

This links the calendar behavior with modal-driven task creation.

7. Final Result

Once configured, your Dispatcher Workspace will support:

- Drag-to-create Work Order Tasks

- Double-click-to-create Work Order Tasks

- Automatic technician and time slot population

- Modal-driven task creation

This provides a familiar, Outlook-like scheduling experience.

Selected timeslot 6:00:00 – 7:00:00 on 24th November across Alex Ray

RamyaV_60-1763987783107.png

RamyaV_61-1763987795756.png

 

 

 

3 REPLIES 3

Mohammed8
Mega Sage

Hi @Ramya V ,

Nice article and a very practical use case! Definitely worth trying out 

Thanks for sharing this

 

Regards,

Mohammed Zakir

Skylar_Barth
ServiceNow Employee
ServiceNow Employee

Incredible article, can't wait to dive in deeper. Will share with channels.

Joshua Chen MTL
Mega Sage

@Ramya V  cool stuff,
wonder if this customization is worth it vs simply using the contextual side panel. thoughts on effort/technical debt?

have you extended your solution and tested:

  • have you tested it with WFO also?
  • does it block agent calendar, you re using ootb work task event? 
  • does it work with dynamic scheduling or schdule op?
  • does it create issue with dispatcher workspace refresh (small refresh and the big refresh)?
  • timezones handling?
  • have you tested if this conflict with intelligent task recommendation (click and drag)???
  • does it also replicate across manager workspace or workforce as an event?

i think your solution is a cool idea, it could also be very useful to have this instead of the contextual side panel to add events (not just personal events) ; ootb, currently it has very limited fields 

.
Add me on LinkedIn 🙂 https://www.linkedin.com/in/joshuachen0510/