---
title: "Vue Timeline Cross-Instance Drag and Drop Example | Mobiscroll"
component: "Timeline"
framework: "Vue"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/vue/timeline/drag-drop-between-calendar-instances"
---

# Cross-Instance Drag and Drop - Vue Timeline demo

Drag and drop events between two Vue Timeline views to reassign resources or coordinate schedules — enable cross-timeline transfers. For Vue and Nuxt.

- [Live demo](https://demo.mobiscroll.com/vue/timeline/drag-drop-between-calendar-instances)
- [View SFC JS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue/tree/main/src/demos/eventcalendar/timeline/drag-drop-between-calendar-instances)
- [View SFC TS code on GitHub](https://github.com/acidb/mobiscroll-demos-vue-ts/tree/main/src/demos/eventcalendar/timeline/drag-drop-between-calendar-instances)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/timeline/drag-drop-between-calendar-instances.md), [jQuery](https://demo.mobiscroll.com/jquery/timeline/drag-drop-between-calendar-instances.md), [Angular](https://demo.mobiscroll.com/angular/timeline/drag-drop-between-calendar-instances.md), [React](https://demo.mobiscroll.com/react/timeline/drag-drop-between-calendar-instances.md)

## Description

There are certain cases when moving the events between calendars can come in handy.

Dragging and dropping events between two timeline instances can be enabled by turning on the [`externalDrag`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-externalDrag) and [`externalDrop`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-externalDrop) options.

**Want to learn about how you can configure the horizontal and vertical resolution?** [Check out how to build a synchronized flight scheduling dashboard →](https://demo.mobiscroll.com/vue/timeline/flight-scheduling-two-synchronized-timelines)

## What this demo shows

- Two separate monthly timeline instances are displayed one below the other, where days are arranged horizontally and resources are listed as rows on the left.
- **Header navigation** The month and year label opens date navigation, while the previous and next arrows move between weeks and the Today button returns to the current date.
- **Month view** The strip below the header show days of the selected month, with the current date highlighted.
- **Resources** Multiple resources are shown as separate timeline rows.
- **Event cards** Events are shown as colored cards with a left color stripe, a bold title, and the start and end time of the event below the title.
- **External drag and drop** Events can be dragged from one timeline instance and dropped into the other to move them between the two timelines.
- **Date positioning** Events are positioned by their assigned resource and exact date range.
- **Event interaction** Events highlight on hover and show drag and resize handles for repositioning or changing duration.
- **Event selection** Clicking an event selects and highlights it.
- **Event creation** New events can be created by double-clicking the timeline or by clicking and dragging across a time range.
- **Scrolling** The timeline supports horizontal and vertical scrolling for navigating through time and resources.

## Best for

- **Multi-timeline planning** Moving events between separate team, department, or location calendars.
- **Resource reassignment** Reassigning appointments, tasks, or shifts from one timeline to another with direct drag and drop.
- **Parallel timeline review** Comparing two weekly timelines and adjusting event placement between them.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-themeVariant) - option
- [`view`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-view) - option
- [`data`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-data) - option
- [`resources`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-resources) - option
- [`height`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-height) - option
- [`dragToMove`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-dragToMove) - option
- [`eventDelete`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-eventDelete) - option
- [`externalDrag`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-externalDrag) - option
- [`externalDrop`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-externalDrop) - option
- [`event-created`](https://mobiscroll.com/docs/vue/eventcalendar/api#event-onEventCreated) - event
- [`close`](https://mobiscroll.com/docs/vue/notifications/toast#event-onClose) - event

## Code

### SFC JS

```vue
<script setup>
import {
  MbscEventcalendar,
  MbscPage,
  MbscToast,
  setOptions
} from '@mobiscroll/vue'
import { ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myView = {
  timeline: { type: 'month' }
}

const firstEvents = ref([
  {
    start: '2026-10-02T00:00',
    end: '2026-10-05T00:00',
    title: 'Event 1',
    color: '#166f6f',
    resource: 1
  },
  {
    start: '2026-10-15T00:00',
    end: '2026-10-19T00:00',
    title: 'Event 2',
    color: '#e20000',
    resource: 1
  },
  {
    start: '2026-10-10T00:00',
    end: '2026-10-14T00:00',
    title: 'Event 3',
    color: '#1dab2f',
    resource: 2
  },
  {
    start: '2026-10-20T00:00',
    end: '2026-10-23T00:00',
    title: 'Event 4',
    color: '#e25dd2',
    resource: 2
  },
  {
    start: '2026-10-03T00:00',
    end: '2026-10-10T00:00',
    title: 'Event 5',
    color: '#4418d2',
    resource: 3
  },
  {
    start: '2026-10-16T00:00',
    end: '2026-10-19T00:00',
    title: 'Event 6',
    color: '#4981d6',
    resource: 3
  },
  {
    start: '2026-10-08T00:00',
    end: '2026-10-12T00:00',
    title: 'Event 7',
    color: '#6e7f29',
    resource: 4
  },
  {
    start: '2026-10-22T00:00',
    end: '2026-10-28T00:00',
    title: 'Event 8',
    color: '#8b8b00',
    resource: 4
  },
  {
    start: '2026-10-02T00:00',
    end: '2026-10-07T00:00',
    title: 'Event 9',
    color: '#a32f00',
    resource: 5
  },
  {
    start: '2026-10-18T00:00',
    end: '2026-10-23T00:00',
    title: 'Event 10',
    color: '#152d2b',
    resource: 5
  }
])

const firstResources = ref([
  {
    id: 1,
    name: 'Resource A'
  },
  {
    id: 2,
    name: 'Resource B'
  },
  {
    id: 3,
    name: 'Resource C'
  },
  {
    id: 4,
    name: 'Resource D'
  },
  {
    id: 5,
    name: 'Resource E'
  }
])

const secondEvents = ref([
  {
    start: '2026-10-05T00:00',
    end: '2026-10-09T00:00',
    title: 'Event 1',
    color: '#4418d2',
    resource: 1
  },
  {
    start: '2026-10-16T00:00',
    end: '2026-10-20T00:00',
    title: 'Event 2',
    color: '#8b1a1a',
    resource: 1
  },
  {
    start: '2026-10-08T00:00',
    end: '2026-10-11T00:00',
    title: 'Event 3',
    color: '#e7b300',
    resource: 2
  },
  {
    start: '2026-10-22T00:00',
    end: '2026-10-25T00:00',
    title: 'Event 4',
    color: '#a32f00',
    resource: 2
  },
  {
    start: '2026-10-12T00:00',
    end: '2026-10-17T00:00',
    title: 'Event 5',
    color: '#21a833',
    resource: 3
  },
  {
    start: '2026-10-23T00:00',
    end: '2026-10-29T00:00',
    title: 'Event 6',
    color: '#a917bb',
    resource: 3
  },
  {
    start: '2026-10-04T00:00',
    end: '2026-10-10T00:00',
    title: 'Event 7',
    color: '#e20000',
    resource: 4
  },
  {
    start: '2026-10-18T00:00',
    end: '2026-10-25T00:00',
    title: 'Event 8',
    color: '#4981d6',
    resource: 4
  },
  {
    start: '2026-10-07T00:00',
    end: '2026-10-12T00:00',
    title: 'Event 9',
    color: '#166f6f',
    resource: 5
  },
  {
    start: '2026-10-20T00:00',
    end: '2026-10-27T00:00',
    title: 'Event 10',
    color: '#d6d145',
    resource: 5
  }
])

const secondResources = ref([
  {
    id: 1,
    name: 'Resource A'
  },
  {
    id: 2,
    name: 'Resource B'
  },
  {
    id: 3,
    name: 'Resource C'
  },
  {
    id: 4,
    name: 'Resource D'
  },
  {
    id: 5,
    name: 'Resource E'
  }
])

const toastMessage = ref('')
const toastContext = ref()
const isToastOpen = ref(false)

function handleFirstCalEventCreated(args) {
  if (args.action === 'externalDrop') {
    toastMessage.value = 'Event dropped to Calendar 1'
    toastContext.value = '.md-drag-drop-first-calendar'
    isToastOpen.value = true
  }
}

function handleSecondCalEventCreated(args) {
  if (args.action === 'externalDrop') {
    toastMessage.value = 'Event dropped to Calendar 2'
    toastContext.value = '.md-drag-drop-second-calendar'
    isToastOpen.value = true
  }
}

function handleToastClose() {
  isToastOpen.value = false
}
</script>

<template>
  <MbscPage>
    <div class="md-drag-drop-calendar">
      <div class="mbsc-form-group-title">Calendar 1</div>
      <MbscEventcalendar
        :view="myView"
        :data="firstEvents"
        :resources="firstResources"
        :height="420"
        :dragToMove="true"
        :eventDelete="true"
        :externalDrag="true"
        :externalDrop="true"
        @event-created="handleFirstCalEventCreated"
        className="md-drag-drop-first-calendar"
      />

      <div class="mbsc-form-group-title">Calendar 2</div>
      <MbscEventcalendar
        :view="myView"
        :data="secondEvents"
        :resources="secondResources"
        :height="420"
        :dragToMove="true"
        :eventDelete="true"
        :externalDrag="true"
        :externalDrop="true"
        @event-created="handleSecondCalEventCreated"
        className="md-drag-drop-second-calendar"
      />

      <MbscToast
        :message="toastMessage"
        :context="toastContext"
        :isOpen="isToastOpen"
        @close="handleToastClose"
      />
    </div>
  </MbscPage>
</template>
```

### SFC TS

```vue
<script setup lang="ts">
import {
  MbscEventcalendar,
  MbscPage,
  MbscToast,
  setOptions
} from '@mobiscroll/vue'
import type {
  MbscCalendarEvent,
  MbscEventcalendarView,
  MbscEventCreatedEvent,
  MbscResource
} from '@mobiscroll/vue'
import { ref } from 'vue'

setOptions({
  theme: 'ios',
  themeVariant: 'light'
})

const myView: MbscEventcalendarView = {
  timeline: { type: 'month' }
}

const firstEvents = ref<MbscCalendarEvent[]>([
  {
    start: '2026-10-02T00:00',
    end: '2026-10-05T00:00',
    title: 'Event 1',
    color: '#166f6f',
    resource: 1
  },
  {
    start: '2026-10-15T00:00',
    end: '2026-10-19T00:00',
    title: 'Event 2',
    color: '#e20000',
    resource: 1
  },
  {
    start: '2026-10-10T00:00',
    end: '2026-10-14T00:00',
    title: 'Event 3',
    color: '#1dab2f',
    resource: 2
  },
  {
    start: '2026-10-20T00:00',
    end: '2026-10-23T00:00',
    title: 'Event 4',
    color: '#e25dd2',
    resource: 2
  },
  {
    start: '2026-10-03T00:00',
    end: '2026-10-10T00:00',
    title: 'Event 5',
    color: '#4418d2',
    resource: 3
  },
  {
    start: '2026-10-16T00:00',
    end: '2026-10-19T00:00',
    title: 'Event 6',
    color: '#4981d6',
    resource: 3
  },
  {
    start: '2026-10-08T00:00',
    end: '2026-10-12T00:00',
    title: 'Event 7',
    color: '#6e7f29',
    resource: 4
  },
  {
    start: '2026-10-22T00:00',
    end: '2026-10-28T00:00',
    title: 'Event 8',
    color: '#8b8b00',
    resource: 4
  },
  {
    start: '2026-10-02T00:00',
    end: '2026-10-07T00:00',
    title: 'Event 9',
    color: '#a32f00',
    resource: 5
  },
  {
    start: '2026-10-18T00:00',
    end: '2026-10-23T00:00',
    title: 'Event 10',
    color: '#152d2b',
    resource: 5
  }
])

const firstResources = ref<MbscResource[]>([
  {
    id: 1,
    name: 'Resource A'
  },
  {
    id: 2,
    name: 'Resource B'
  },
  {
    id: 3,
    name: 'Resource C'
  },
  {
    id: 4,
    name: 'Resource D'
  },
  {
    id: 5,
    name: 'Resource E'
  }
])

const secondEvents = ref<MbscCalendarEvent[]>([
  {
    start: '2026-10-05T00:00',
    end: '2026-10-09T00:00',
    title: 'Event 1',
    color: '#4418d2',
    resource: 1
  },
  {
    start: '2026-10-16T00:00',
    end: '2026-10-20T00:00',
    title: 'Event 2',
    color: '#8b1a1a',
    resource: 1
  },
  {
    start: '2026-10-08T00:00',
    end: '2026-10-11T00:00',
    title: 'Event 3',
    color: '#e7b300',
    resource: 2
  },
  {
    start: '2026-10-22T00:00',
    end: '2026-10-25T00:00',
    title: 'Event 4',
    color: '#a32f00',
    resource: 2
  },
  {
    start: '2026-10-12T00:00',
    end: '2026-10-17T00:00',
    title: 'Event 5',
    color: '#21a833',
    resource: 3
  },
  {
    start: '2026-10-23T00:00',
    end: '2026-10-29T00:00',
    title: 'Event 6',
    color: '#a917bb',
    resource: 3
  },
  {
    start: '2026-10-04T00:00',
    end: '2026-10-10T00:00',
    title: 'Event 7',
    color: '#e20000',
    resource: 4
  },
  {
    start: '2026-10-18T00:00',
    end: '2026-10-25T00:00',
    title: 'Event 8',
    color: '#4981d6',
    resource: 4
  },
  {
    start: '2026-10-07T00:00',
    end: '2026-10-12T00:00',
    title: 'Event 9',
    color: '#166f6f',
    resource: 5
  },
  {
    start: '2026-10-20T00:00',
    end: '2026-10-27T00:00',
    title: 'Event 10',
    color: '#d6d145',
    resource: 5
  }
])

const secondResources = ref<MbscResource[]>([
  {
    id: 1,
    name: 'Resource A'
  },
  {
    id: 2,
    name: 'Resource B'
  },
  {
    id: 3,
    name: 'Resource C'
  },
  {
    id: 4,
    name: 'Resource D'
  },
  {
    id: 5,
    name: 'Resource E'
  }
])

const toastContext = ref<string>()
const toastMessage = ref<string>('')
const isToastOpen = ref<boolean>(false)

function handleFirstCalEventCreated(args: MbscEventCreatedEvent) {
  if (args.action === 'externalDrop') {
    toastMessage.value = 'Event dropped to Calendar 1'
    toastContext.value = '.md-drag-drop-first-calendar'
    isToastOpen.value = true
  }
}

function handleSecondCalEventCreated(args: MbscEventCreatedEvent) {
  if (args.action === 'externalDrop') {
    toastMessage.value = 'Event dropped to Calendar 2'
    toastContext.value = '.md-drag-drop-second-calendar'
    isToastOpen.value = true
  }
}

function handleToastClose() {
  isToastOpen.value = false
}
</script>

<template>
  <MbscPage>
    <div class="md-drag-drop-calendar">
      <div class="mbsc-form-group-title">Calendar 1</div>
      <MbscEventcalendar
        :view="myView"
        :data="firstEvents"
        :resources="firstResources"
        :height="420"
        :dragToMove="true"
        :eventDelete="true"
        :externalDrag="true"
        :externalDrop="true"
        @event-created="handleFirstCalEventCreated"
        className="md-drag-drop-first-calendar"
      />

      <div class="mbsc-form-group-title">Calendar 2</div>
      <MbscEventcalendar
        :view="myView"
        :data="secondEvents"
        :resources="secondResources"
        :height="420"
        :dragToMove="true"
        :eventDelete="true"
        :externalDrag="true"
        :externalDrop="true"
        @event-created="handleSecondCalEventCreated"
        className="md-drag-drop-second-calendar"
      />

      <MbscToast
        :message="toastMessage"
        :context="toastContext"
        :isOpen="isToastOpen"
        @close="handleToastClose"
      />
    </div>
  </MbscPage>
</template>
```

## Implementation notes

- Render two independent `Eventcalendar` instances on the same page, each with `timeline: { type: 'month' }` and `height: 420`.
- Each instance has its own separate dataset: 5 resources (A-E) and 10 events with `dyndatetime` offsets spread across the current month.
- Enable on both instances: `dragToMove: true`, `eventDelete: true`, `externalDrag: true`, `externalDrop: true`. Both `externalDrag` and `externalDrop` must be set on both calendars to allow bidirectional transfer - `externalDrag` permits dragging an event out, `externalDrop` permits receiving a drop from another instance.
- Handle `onEventCreated` on each instance. Inside the handler, check `args.action === 'externalDrop'` to distinguish a cross-calendar drop from a regular click-to-create or drag-to-create. When the condition is true, show a `Toast` confirming which calendar received the event.
- Scope each `Toast` to its calendar using the `context` prop (a CSS class or element selector pointing to the receiving calendar's wrapper). This positions the toast near the correct calendar rather than at the page level.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-vue.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config vue
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config vue --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/vue/getting-started/installation

## Related demos

- Previous: [Drag & Drop Restrictions per Event & Resource](https://demo.mobiscroll.com/vue/timeline/conditional-move-resize-drag-drop-fixed-event-length-fixed-to-resource.md) - Restrict drag, move, and resize on a Vue Timeline per event, resource, or globally — lock events in time, fix length, or prevent resource switches.
- Next: [Prevent Event Overlap](https://demo.mobiscroll.com/vue/timeline/prevent-double-booking-events.md) - Prevent double booking on the Vue Timeline — block overlaps per event, per resource, or globally, and show a toast on conflict.
