---
title: "Angular Event calendar Drag-and-Drop Task Presets Example | Mobiscroll"
component: "Event calendar"
framework: "Angular"
library_version: "6.2.0"
url: "https://demo.mobiscroll.com/angular/eventcalendar/external-event-presets"
---

# Drag-and-Drop Task Presets - Angular Event calendar demo

Drag preset task templates from an external list onto an Angular event calendar — a popup form captures task details and technician at drop time.

- [Live demo](https://demo.mobiscroll.com/angular/eventcalendar/external-event-presets)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-angular/tree/main/src/demos/eventcalendar/calendar-view/external-event-presets)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/eventcalendar/external-event-presets.md), [jQuery](https://demo.mobiscroll.com/jquery/eventcalendar/external-event-presets.md), [React](https://demo.mobiscroll.com/react/eventcalendar/external-event-presets.md), [Vue](https://demo.mobiscroll.com/vue/eventcalendar/external-event-presets.md)

## Description

Use external draggable events to create preset tasks that people can quickly copy and spawn events from. A great example is a car wrapping shop where different jobs need to be set up depending on the type of vehicle.

Print a list of predefined tasks and initialize them as `draggable` elements. Enable [`externalDrop`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-externalDrop) for the calendar and set up the predefined event skeletons for the [draggable](https://mobiscroll.com/docs/angular/eventcalendar/drag-and-drop#targeting-the-eventcalendar) component.

Whenever there is more information to be captured, like detailed task notes, customer information, the name of the technician... you can trigger a `popup` with the task form in the [`onEventCreate`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onEventCreate) lifecycle event. For failed drops (trying to schedule a task during lunch breaks or weekends) the [`onEventCreateFailed`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onEventCreateFailed) event will be triggered.

**Want to see how external presets look & feel for a scheduler?** [Check out this example →](https://demo.mobiscroll.com/angular/scheduler/external-event-presets)

## What this demo shows

- A desktop month view event calendar paired with an external list of predefined tasks that can be dragged onto the calendar.
- **Calendar layout** The main view shows a full month grid with no events.
- **Calendar header** The header shows the current month and year on the left, and blue month navigation arrows with a `Today` button between them on the right.
- **Invalid dates** Weekend days are disabled, so they cannot be used as drop targets for new tasks. When a user tries to drop an event in a restricted cell, a `Can't create event on this date` toast appears at the bottom center of the calendar.
- **External task list** A right-side panel titled `Available tasks` displays preset items: `Small wrap 2 day`, `Full-size wrap 3 days`, `Mid-size wrap 3 days`, `Roadster wrap 3 days`, `SUV wrap 4 days`, and `Hypercar wrap 5 days`.
- **External drag & drop** Tasks can be dragged from the external list and dropped onto a calendar day to schedule predefined events.
- **Created event display** Dropping the task opens a popup below the event label with the title `Assign task`.
- **Popup form** The popup includes a `Task` text field prefilled with the task title, a `Details` text field with the `Add description…` placeholder, and a `Technician` select with the `Please select…` placeholder.
- **Popup confirmation** The popup footer contains a blue `Ok` button in the bottom-right corner to confirm the event details.
- **Scheduled task** After a successful drop and confirmation the task label appears inside day cell and a confirmation toast appears on the bottom center part of the calendar with this message `New task added`.
- **Day cell states** Hovering a day cell highlights the day number with a gray background, while clicking the empty part of the cell selects the day and highlights the day number with a blue background.
- **Gesture navigation** The month view can also be changed by clicking and dragging the calendar left or right.

## Best for

- **Service scheduling** Planning repeatable job types, such as vehicle wrapping tasks, from predefined task templates.
- **Template-based booking** Letting teams create new calendar events by dragging standard task presets onto available dates.
- **Technician assignment workflows** Capturing extra scheduling details, such as notes and technician selection, at the moment a task is placed.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-themeVariant) - option
- [`view`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-view) - option
- [`labels`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-labels) - option
- [`invalid`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-invalid) - option
- [`dragToMove`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-dragToMove) - option
- [`externalDrop`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-externalDrop) - option
- [`onEventCreated`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onEventCreated) - event
- [`onEventCreateFailed`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onEventCreateFailed) - event
- [`onEventUpdateFailed`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onEventUpdateFailed) - event
- [`anchor`](https://mobiscroll.com/docs/angular/popup/api#opt-anchor) - option
- [`display`](https://mobiscroll.com/docs/angular/popup/api#opt-display) - option
- [`width`](https://mobiscroll.com/docs/angular/popup/api#opt-width) - option
- [`touchUi`](https://mobiscroll.com/docs/angular/popup/api#opt-touchUi) - option
- [`headerText`](https://mobiscroll.com/docs/angular/popup/api#opt-headerText) - option
- [`buttons`](https://mobiscroll.com/docs/angular/popup/api#opt-buttons) - option
- [`onClose`](https://mobiscroll.com/docs/angular/popup/api#event-onClose) - event
- [`data`](https://mobiscroll.com/docs/angular/select/api#opt-data) - option
- [`label`](https://mobiscroll.com/docs/angular/select/api#opt-label) - option
- [`display`](https://mobiscroll.com/docs/angular/select/api#opt-display) - option
- [`touchUi`](https://mobiscroll.com/docs/angular/select/api#opt-touchUi) - option

## Code

### Component

```ts
import { CommonModule } from '@angular/common';
import { Component, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MbscEventcalendarOptions, MbscModule, MbscPopup, Notifications, setOptions } from '@mobiscroll/angular';

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

@Component({
  selector: 'app-root', 
  templateUrl: './app.component.html',
  providers: [Notifications],
  standalone: true,
  imports: [CommonModule, FormsModule, MbscModule],
})
export class AppComponent {
  constructor(private notify: Notifications) {}
  @ViewChild('popup', { static: false })
  popup!: MbscPopup;

  calendarOptions: MbscEventcalendarOptions = {
    view: {
      calendar: { labels: true },
    },
    invalid: [
      {
        recurring: {
          repeat: 'weekly',
          weekDays: 'SA,SU',
        },
      },
    ],
    dragToMove: true,
    externalDrop: true,
    onEventCreated: (args) => {
      setTimeout(() => {
        this.fillDialog(args);
      });
    },
    onEventCreateFailed: () => {
      this.notify.toast({
        message: "Can't create event on this date",
      });
    },
    onEventUpdateFailed: () => {
      this.notify.toast({
        message: "Can't add event on this date",
      });
    },
  };

  tasks = [
    {
      title: 'Small wrap',
      color: '#637e57',
      start: '2026-11-06T00:00',
      end: '2026-11-07T00:00',
      length: '2 days',
    },
    {
      title: 'Full-size wrap',
      color: '#50789d',
      start: '2026-11-06T00:00',
      end: '2026-11-08T00:00',
      length: '3 days',
    },
    {
      title: 'Mid-size wrap',
      color: '#6c5d45',
      start: '2026-11-06T00:00',
      end: '2026-11-08T00:00',
      length: '3 days',
    },
    {
      title: 'Roadster wrap',
      color: '#9da721',
      start: '2026-11-06T00:00',
      end: '2026-11-08T00:00',
      length: '3 days',
    },
    {
      title: 'SUV wrap',
      color: '#cd6957',
      start: '2026-11-06T00:00',
      end: '2026-11-09T00:00',
      length: '4 days',
    },
    {
      title: 'Hypercar wrap',
      color: '#7a5886',
      start: '2026-11-06T00:00',
      end: '2026-11-10T00:00',
      length: '5 days',
    },
  ];

  myData = [
    { value: '1', text: 'Roly Chester' },
    { value: '2', text: 'Tucker Wayne' },
    { value: '3', text: 'Baker Brielle' },
    { value: '4', text: 'Jami Walter' },
    { value: '5', text: 'Patrick Toby' },
    { value: '6', text: 'Tranter Logan' },
    { value: '7', text: 'Payton Sinclair' },
  ];

  title = '';
  details = '';
  technician = '';
  anchor: HTMLElement | undefined;
  isOpen = false;

  fillDialog(args: any): void {
    this.title = args.event.title;
    this.details = args.event.details;
    this.technician = args.event.technician;
    this.anchor = args.target;
    this.popup.open();
  }

  onClose(): void {
    this.notify.toast({
      message: 'New task added',
    });
  }
}
```

### Template

```html
<div class="mbsc-grid mbsc-no-padding">
  <div class="mbsc-row">
    <div class="mbsc-col-sm-9 external-event-calendar">
      <mbsc-eventcalendar [options]="calendarOptions"></mbsc-eventcalendar>
    </div>
    <div class="mbsc-col-sm-3">
      <div class="mbsc-form-group-title">Available tasks</div>
      <div
        mbsc-draggable
        *ngFor="let task of tasks;let i = index"
        [dragData]="tasks[i]"
        class="external-event-task"
        [ngStyle]="{background: task.color}"
      >
        <div>{{task.title}}</div>
        <div>{{task.length}}</div>
      </div>
    </div>
    <mbsc-popup
      display="anchored"
      [width]="400"
      [contentPadding]="false"
      [touchUi]="false"
      headerText="Assign task"
      [buttons]="['ok']"
      [anchor]="anchor"
      (onClose)="onClose()"
      #popup
    >
      <div class="mbsc-form-group">
        <mbsc-input label="Task" [(ngModel)]="title" [readonly]="true"></mbsc-input>
        <mbsc-textarea label="Details" [(ngModel)]="details" placeholder="Add description..."></mbsc-textarea>
        <mbsc-select
          [(ngModel)]="technician"
          [data]="myData"
          label="Technician"
          display="anchored"
          [touchUi]="false"
          placeholder="Please select..."
        ></mbsc-select>
      </div>
    </mbsc-popup>
  </div>
</div>
```

### CSS

```css
.external-event-calendar {
  border-right: 1px solid #ccc;
}

.external-event-task {
  color: #fff;
  padding: 10px;
  margin: 20px;
  border-radius: 8px;
  font-family:
    -apple-system,
    Segoe UI,
    Roboto,
    sans-serif;
}

.demo-external-event-presets.demo-wrapper,
.demo-external-event-presets .mbsc-grid,
.demo-external-event-presets .mbsc-row,
.demo-external-event-presets .external-event-calendar {
  height: 100%;
}
```

## Implementation notes

- Set `view: { calendar: { labels: true } }`. Enable `externalDrop: true` to accept drops from outside the calendar and `dragToMove: true` to allow moving already-placed events. Block weekends with `invalid: [{ recurring: { repeat: 'weekly', weekDays: 'SA,SU' } }]`.
- Define each preset task as an object with `title`, `color`, `start`, and `end` fields (where `start`/`end` represent today-relative offsets that set the event duration when dropped). Render the task list outside the calendar and initialize each item as a draggable element using the `Draggable` component with `dragData` set to the task object. Angular: use the `mbsc-draggable` directive with `[dragData]`. JS/jQuery: call `mobiscroll.draggable(element, { dragData: task })` for each task element.
- Handle `onEventCreated` (Vue: `@event-created`) after a successful drop: open an anchored `Popup` targeting `args.target` with `display="anchored"`. The popup contains a read-only `Input` prefilled with `args.event.title`, a `Textarea` for details, and a `Select` for technician assignment, with an `['ok']` button to confirm. Show a `Toast` with `'New task added'` when the popup closes. Angular: use `@ViewChild` to get the `MbscPopup` instance and call `.open()` imperatively.
- Handle `onEventCreateFailed` and `onEventUpdateFailed` (Vue: `@event-create-failed`, `@event-update-failed`) to show a `Toast` when a drop lands on a weekend or other invalid date.

## 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-angular.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 angular
   ```

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

   ```
   npm install
   ```

6. Run the project:

   ```
   ng serve
   ```

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

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

## Related demos

- Previous: [Double Booking Prevention](https://demo.mobiscroll.com/angular/eventcalendar/prevent-double-booking-events.md) - Prevent overlapping events in an Angular event calendar — block double bookings per event or across all events with in-calendar conflict alerts.
- Next: [Drag and Drop from External Lists](https://demo.mobiscroll.com/angular/eventcalendar/external-drag-drop-sortable-dragula.md) - Drag items from external SortableJS or Dragula lists onto an Angular event calendar to schedule events — or drag them out to unschedule.
