---
title: "Angular Scheduler Prevent Double Booking Example | Mobiscroll"
component: "Scheduler"
framework: "Angular"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/angular/scheduler/prevent-double-booking-events"
---

# Prevent Double Booking - Angular Scheduler demo

Use the Angular Scheduler to block event overlaps per event, per resource, or globally — with toast notifications when a conflict is blocked. For Angular 22 and Ionic 8.

- [Live demo](https://demo.mobiscroll.com/angular/scheduler/prevent-double-booking-events)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-angular/tree/main/src/demos/eventcalendar/scheduler/prevent-double-booking-events)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/scheduler/prevent-double-booking-events.md), [jQuery](https://demo.mobiscroll.com/jquery/scheduler/prevent-double-booking-events.md), [React](https://demo.mobiscroll.com/react/scheduler/prevent-double-booking-events.md), [Vue](https://demo.mobiscroll.com/vue/scheduler/prevent-double-booking-events.md)

## Description

Sometimes it is necessary to guarantee that events don't overlap - eg. when scheduling workorders, interacting with a work calendar. You can reject the updates or additions and let the user know about it.

The event overlap can be turned on/off on an event basis, per resource or globally on the instance.

- On an [event](https://demo.mobiscroll.com/angular/scheduler/event-data-structure) basis - by setting the `overlap` property to `false` the specified event cannot overlap.
- Per [resource](https://demo.mobiscroll.com/angular/scheduler/resource-data-structure) - by setting the `eventOverlap` property to `false` the events in the specified resource cannot overlap.
- Globally on the instance - by setting [`eventOverlap`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-eventOverlap) option to `false` overlap is disbled globally.

If set to `false`, the [resource](https://demo.mobiscroll.com/angular/scheduler/resource-data-structure) and the [event](https://demo.mobiscroll.com/angular/scheduler/event-data-structure) settings have precedence over the global calendar [`eventOverlap`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-eventOverlap) option.

Give feedback to the user - optionally, a toast can be displayed to explain why an event cannot be dropped, moved or created. For this we can use the `onEventCreateFailed` and `onEventUpdateFailed` lifecycle events.

**Looking to implement time off or block out ranges?** [Learn how to add lunch breaks, working hours and disable weekends →](https://demo.mobiscroll.com/angular/scheduler/time-off-blocked-ranges)

## What this demo shows

- A desktop day scheduler with date navigation, multiple resources, and a vertically scrollable time grid for the selected day.
- **Header navigation** The month and year label in the top left opens date navigation, while the blue previous and next arrows and the Today button on the right make it easy to move between days and jump back to the current day.
- **Day header** The short weekday name and the selected date are shown below the main navigation.
- **Resource strip** Four resources are displayed across the scheduler: Resource 1, Resource 2, Resource 3, and Resource 4 - no event overlap allowed.
- **Event-level restrictions** Resource 1 and Resource 2 contain events with per-event overlap restrictions. Event 2 on Resource 1 and Event 4 on Resource 2 have `overlap: false`, meaning those specific events cannot overlap with any other event. Other events on the same resources can still overlap when the global overlap setting allows it.
- **Resource-level restrictions** Resource 4 - no event overlap allowed has `eventOverlap: false`, which applies a no-overlap rule to every event on that resource.
- **Global overlap control** A switch under this title: `Control the interaction globally (all events/resources)` lets users enable `Events cannot overlap eventOverlap=false` to prevent overlaps across all the scheduler, by default it's disabled. 
- **Time grid** The scheduler grid scrolls vertically through the hours of the selected day.
- **Current time** A horizontal blue line marks the current time across the scheduler.
- **Hover feedback** Hovering over the time grid shows a time indicator that follows the pointer in 15-minute increments.
- **Timed events** Events are displayed as ligh blue cards with a blue left stripe, the event title, and the exact start and end time.
- **Event interaction** Hovering over events highlights them and shows drag and resize handles when the event allows those interactions.
- **Event selection** Clicking an event selects and highlights it.
- **Event creation** Double-clicking the time grid or clicking and dragging on it creates a new event.
- **Creation feedback** When a user tries to create an overlapping event in a restricted cell, a `Make sure not to overbook` toast appears at the bottom center of the calendar.

## Best for

- **Work orders and field service** Preventing technicians, crews, or jobs from being booked into the same time slot.
- **Availability-sensitive booking** Handling internal planning or booking workflows where double booking must be prevented for specific event types, resources, or the entire calendar.
- **Shared resource scheduling** Managing rooms, equipment, vehicles, or other resources that can only be assigned to one event at a time.
- **Interactive planning tools** Giving users immediate feedback when an action would create a scheduling conflict.
- **Mixed scheduling policies** Combining global, resource-level, and event-level overlap rules within the same scheduler.

## Tutorial

### Control the interaction globally (all events/resources)

- [ ] Events cannot overlap `eventOverlap=false`

```html
<mbsc-eventcalendar
    [view]="{ scheduler: { type: 'day' }}"
    [data]="myData"
    [resources]="myResources"
    [dragToMove]="true"
    [dragToResize]="true"
    [eventOverlap]="true"
    [clickToCreate]="true"
    [dragToCreate]="true"
>
</mbsc-eventcalendar>
```

```ts
// relevant events
const myData = [{
    start: '2026-10-22T16:00',
    end: '2026-10-22T17:00',
    title: 'Event 2 (no event overlap)',
    overlap: false,
    resource: 1
},{
    start: '2026-10-22T08:00',
    end: '2026-10-22T10:00',
    title: 'Event 4 (no event overlap)',
    overlap: false,
    resource: 2
}];
// relevant resource
const myResources = [{
    id: 4,
    name: 'Resource 4 - no event overlap allowed',
    eventOverlap: false
}];
```

## 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
- [`clickToCreate`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-clickToCreate) - option
- [`dragToCreate`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-dragToCreate) - option
- [`dragToMove`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-dragToMove) - option
- [`dragToResize`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-dragToResize) - option
- [`eventOverlap`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-eventOverlap) - option
- [`onEventUpdateFailed`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onEventUpdateFailed) - event
- [`onEventCreateFailed`](https://mobiscroll.com/docs/angular/eventcalendar/api#event-onEventCreateFailed) - event
- [`data`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-data) - option
- [`resources`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-resources) - option
- [`view`](https://mobiscroll.com/docs/angular/eventcalendar/api#opt-view) - option

## Code

### Component

```ts
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import {
  MbscCalendarEvent,
  MbscEventcalendarOptions,
  MbscEventcalendarView,
  MbscModule,
  MbscResource,
  Notifications,
  setOptions,
} from '@mobiscroll/angular';

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

const now = new Date();
const y = now.getFullYear();
const m = now.getMonth();
const d = now.getDate();

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

  myOptions: MbscEventcalendarOptions = {
    clickToCreate: true,
    dragToCreate: true,
    dragToMove: true,
    dragToResize: true,
    eventOverlap: true,
    onEventUpdateFailed: () => {
      this.notify.toast({
        message: 'Make sure not to double book',
      });
    },
    onEventCreateFailed: () => {
      this.notify.toast({
        message: 'Make sure not to double book',
      });
    },
  };

  myEvents: MbscCalendarEvent[] = [
    {
      start: new Date(y, m, d, 11),
      end: new Date(y, m, d, 13),
      title: 'Event 1',
      resource: 1,
    },
    {
      start: new Date(y, m, d, 16),
      end: new Date(y, m, d, 17),
      title: 'Event 2 (no event overlap)',
      overlap: false,
      resource: 1,
    },
    {
      start: new Date(y, m, d, 14),
      end: new Date(y, m, d, 16),
      title: 'Event 3',
      resource: 2,
    },
    {
      start: new Date(y, m, d, 8),
      end: new Date(y, m, d, 10),
      title: 'Event 4 (no event overlap)',
      resource: 2,
      overlap: false,
    },
    {
      start: new Date(y, m, d, 10),
      end: new Date(y, m, d, 13),
      title: 'Event 5',
      resource: 3,
    },
    {
      start: new Date(y, m, d, 11),
      end: new Date(y, m, d, 16),
      title: 'Event 6',
      resource: 4,
    },
  ];

  myResources: MbscResource[] = [
    {
      id: 1,
      name: 'Resource 1',
    },
    {
      id: 2,
      name: 'Resource 2',
    },
    {
      id: 3,
      name: 'Resource 3',
    },
    {
      id: 4,
      name: 'Resource 4 - no event overlap allowed',
      eventOverlap: false,
    },
  ];

  myView: MbscEventcalendarView = {
    scheduler: { type: 'day' },
  };
}
```

### Template

```html
<mbsc-eventcalendar [data]="myEvents" [resources]="myResources" [view]="myView" [options]="myOptions"></mbsc-eventcalendar>
```

## Implementation notes

- Use `view: { scheduler: { type: 'day' } }`. Set `eventOverlap: true` globally so overlap is permitted by default; individual events and resources selectively restrict it.
- Define 4 resources. Resource 4 has `eventOverlap: false` - no event on this resource may overlap with another, regardless of per-event settings.
- Add 6 events for today using `new Date(y, m, d, hour)`. Two events carry `overlap: false` (on Resources 1 and 2); the rest can overlap freely unless their resource blocks it.
- Enable all interactions: `clickToCreate: true`, `dragToCreate: true`, `dragToMove: true`, `dragToResize: true`.
- Handle both `onEventCreateFailed` and `onEventUpdateFailed` to react to a blocked overlap. The calendar automatically rejects and reverts the action.
- **Precedence**: per-event `overlap: false` and per-resource `eventOverlap: false` both override the global `eventOverlap` option.

## 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: [Blocked Time Ranges](https://demo.mobiscroll.com/angular/scheduler/time-off-blocked-ranges.md) - Block weekends, holidays, and lunch breaks in the Angular Scheduler using recurring unavailable ranges — choose strict or start-end validation.
- Next: [External Drag and Drop](https://demo.mobiscroll.com/angular/scheduler/external-drag-drop-sortable-dragula.md) - Connect SortableJS or Dragula lists to the Angular Scheduler — drag items in to schedule events and drag events out to unschedule them.
