---
title: "Vue Event calendar Blocked Days and Date Ranges Example | Mobiscroll"
component: "Event calendar"
framework: "Vue"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/vue/eventcalendar/blocked-days-ranges"
---

# Blocked Days and Date Ranges - Vue Event calendar demo

Disable weekends and date ranges in a Vue event calendar — block dates and drag-and-drop, and choose between strict or permissive validation modes. For Vue and Nuxt.

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

## Description

Entire days and ranges can be blocked out to manage event creation and editing more efficiently.

To disable specific or recurring days you can pass an array to the [`invalid`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-invalid) option. A couple of examples:

- To disable weekends, use the [recurring object](https://demo.mobiscroll.com/vue/eventcalendar/recurring-events) - `recurring: { repeat: 'weekly', weekDays: 'SA,SU' }`
- Disable a specific range - `{ start: new Date(2020, 11, 19), end: new Date(2020, 11, 20) }`

When dragging events onto disabled days, they will automatically be denied and [`event-update-failed`](https://mobiscroll.com/docs/vue/eventcalendar/api#event-onEventCreateFailed) / [`event-create-failed`](https://mobiscroll.com/docs/vue/eventcalendar/api#event-onEventUpdateFailed) events will be triggered, from which custom logic can be executed to show a toast or maybe a modal for data correction. The built-in logic of how the calendar handles validation on user interaction can be controlled through the [`invalidateEvent`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-invalidateEvent) option:

- `'strict'` - Strict being the default, no event overlap is allowed with invalid ranges.
- `'start-end'` - With start-end validation the calendar checks if the start or end of the event coincides with any invalid range. Other overlaps are allowed.

If you're interested in invalids for a given range (including recurring occurrences), you can use the [`getInvalids`](https://mobiscroll.com/docs/vue/eventcalendar/api#method-getInvalids) function.

## What this demo shows

- A desktop month view event calendar shows a full month grid with event labels displayed directly inside the day cells.
- **Invalid days** Weekends are disabled through recurring invalid rules, and additional specific dates are disabled separately.
- **Disabled cell styling** Invalid day cells have a gray overlay that indicates events cannot be created on those days.
- **Month grid** Day cell display events, each event label has a colored line on the left, the event title, and the end time of the event on the right.
- **Event interaction** Hovering over or selecting an event label highlights it and shows resize handles on both sides, indicating that the event can be resized by clicking and dragging.
- **Validation mode selector** A control panel next to the calendar (left side) `Configure the built-in validation` includes two selectable validation modes.
- **Validation options** The first option `Events cannot start or end on invalids, but can overlap` allows events to start and end only on valid dates while still allowing overlap with invalid days.
- **Validation options** The default selected option `Events cannot overlap invalid ranges at all` prevents events from overlapping invalid days.
- **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.
- **Event creation** Clicking and dragging on an empty part of a day cell creates a new event.
- **Validation during creation** Event creation follows the active validation mode and is blocked on invalid dates or invalid overlaps based on the selected option.
- **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.

## Best for

- **Booking and availability rules** Useful when certain days must stay unavailable for booking, scheduling, or reservation creation.
- **Office closures and non-working days** A good fit for workflows where weekends, holidays, or blackout dates should not accept new events.
- **Operational scheduling** Works well for teams that need to enforce date-based scheduling restrictions while still allowing users to view existing events.
- **Validation policy comparisons** Helpful when you want to compare stricter invalid-range enforcement with a more permissive start-and-end-only validation rule.

## Tutorial

### Configure the built-in validation

- ( ) Events cannot start or end on invalids, but can overlap
- (x) Events cannot overlap invalid ranges at all

```vue
<script setup>
const toastMessage = ref(null)
const isToastOpen = ref(false)
const myInvalid = [
  {
    recurring: {
      repeat: 'weekly',
      weekDays: 'SA,SU'
    }
  },
  {
    allDay: true,
    start: '2026-10-19T00:00',
    end: '2026-10-20T00:00'
  },
  {
    allDay: true,
    start: '2026-10-26T00:00',
    end: '2026-10-27T00:00',
  }
]

function handleEventCreateFailed() {
  toastMessage.value = "Can't create event on this date"
  isToastOpen.value = true
}

function handleEventUpdateFailed() {
  toastMessage.value = "Can't add event on this date"
  isToastOpen.value = true
}

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

<template>
  <MbscEventcalendar
    :dragToCreate="true"
    :dragToMove="true"
    :dragToResize="true"
    :invalid="myInvalid"
    invalidateEvent="strict"
    @event-create-failed="handleEventCreateFailed"
    @event-update-failed="handleEventUpdateFailed"
  />
  <MbscToast
    :message="toastMessage"
    :isOpen="isToastOpen"
    @close="handleToastClose"
  />
</template>
```

With "Events cannot start or end on invalids, but can overlap":

```vue
<script setup>
const toastMessage = ref(null)
const isToastOpen = ref(false)
const myInvalid = [
  {
    recurring: {
      repeat: 'weekly',
      weekDays: 'SA,SU'
    }
  },
  {
    allDay: true,
    start: '2026-10-19T00:00',
    end: '2026-10-20T00:00'
  },
  {
    allDay: true,
    start: '2026-10-26T00:00',
    end: '2026-10-27T00:00',
  }
]

function handleEventCreateFailed() {
  toastMessage.value = "Can't create event on this date"
  isToastOpen.value = true
}

function handleEventUpdateFailed() {
  toastMessage.value = "Can't add event on this date"
  isToastOpen.value = true
}

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

<template>
  <MbscEventcalendar
    :dragToCreate="true"
    :dragToMove="true"
    :dragToResize="true"
    :invalid="myInvalid"
    invalidateEvent="start-end"
    @event-create-failed="handleEventCreateFailed"
    @event-update-failed="handleEventUpdateFailed"
  />
  <MbscToast
    :message="toastMessage"
    :isOpen="isToastOpen"
    @close="handleToastClose"
  />
</template>
```

## 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
- [`labels`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-labels) - option
- [`data`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-data) - option
- [`view`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-view) - option
- [`invalid`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-invalid) - option
- [`dragToCreate`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-dragToCreate) - option
- [`dragToMove`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-dragToMove) - option
- [`dragToResize`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-dragToResize) - option
- [`invalidateEvent`](https://mobiscroll.com/docs/vue/eventcalendar/api#opt-invalidateEvent) - option
- [`event-create-failed`](https://mobiscroll.com/docs/vue/eventcalendar/api#event-onEventCreateFailed) - event
- [`event-update-failed`](https://mobiscroll.com/docs/vue/eventcalendar/api#event-onEventUpdateFailed) - event
- [`close`](https://mobiscroll.com/docs/vue/notifications/toast#event-onClose) - event

## Code

### SFC JS

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

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

const myEvents = ref([])
const toastMessage = ref(null)
const isToastOpen = ref(false)
const myView = {
  calendar: { labels: true }
}
const myInvalid = [
  {
    recurring: {
      repeat: 'weekly',
      weekDays: 'SA,SU'
    }
  },
  {
    allDay: true,
    start: '2026-10-19T00:00',
    end: '2026-10-20T00:00'
  },
  {
    allDay: true,
    start: '2026-10-26T00:00',
    end: '2026-10-27T00:00'
  }
]

function handleEventCreateFailed() {
  toastMessage.value = "Can't create event on this date"
  isToastOpen.value = true
}

function handleEventUpdateFailed() {
  toastMessage.value = "Can't add event on this date"
  isToastOpen.value = true
}

function handleToastClose() {
  isToastOpen.value = false
}

onMounted(() => {
  getJson(
    'https://trial.mobiscroll.com/work-events/',
    (events) => {
      myEvents.value = events
    },
    'jsonp'
  )
})
</script>

<template>
  <MbscEventcalendar
    :data="myEvents"
    :view="myView"
    :invalid="myInvalid"
    :dragToCreate="true"
    :dragToMove="true"
    :dragToResize="true"
    invalidateEvent="strict"
    @event-create-failed="handleEventCreateFailed"
    @event-update-failed="handleEventUpdateFailed"
  />
  <MbscToast :message="toastMessage" :isOpen="isToastOpen" @close="handleToastClose" />
</template>
```

### SFC TS

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

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

const myEvents = ref<MbscCalendarEvent[]>([])
const toastMessage = ref('')
const isToastOpen = ref(false)
const myView = {
  calendar: { labels: true }
}
const myInvalid = [
  {
    recurring: {
      repeat: 'weekly',
      weekDays: 'SA,SU'
    }
  },
  {
    allDay: true,
    start: '2026-10-19T00:00',
    end: '2026-10-20T00:00'
  },
  {
    allDay: true,
    start: '2026-10-26T00:00',
    end: '2026-10-27T00:00'
  }
]

function handleEventCreateFailed() {
  toastMessage.value = "Can't create event on this date"
  isToastOpen.value = true
}

function handleEventUpdateFailed() {
  toastMessage.value = "Can't add event on this date"
  isToastOpen.value = true
}

function handleToastClose() {
  isToastOpen.value = false
}

onMounted(() => {
  getJson(
    'https://trial.mobiscroll.com/work-events/',
    (events: MbscCalendarEvent[]) => {
      myEvents.value = events
    },
    'jsonp'
  )
})
</script>

<template>
  <MbscEventcalendar
    :data="myEvents"
    :view="myView"
    :invalid="myInvalid"
    :dragToCreate="true"
    :dragToMove="true"
    :dragToResize="true"
    invalidateEvent="strict"
    @event-create-failed="handleEventCreateFailed"
    @event-update-failed="handleEventUpdateFailed"
  />
  <MbscToast :message="toastMessage" :isOpen="isToastOpen" @close="handleToastClose" />
</template>
```

## Implementation notes

- Set `view: { calendar: { labels: true } }`. Enable `dragToCreate: true`, `dragToMove: true`, and `dragToResize: true` so users can create and edit events interactively.
- Pass an `invalid` array to block days. Use a recurring rule for recurring days - for example weekends: `{ recurring: { repeat: 'weekly', weekDays: 'SA,SU' } }`. Block specific date ranges with `{ allDay: true, start: '...', end: '...' }`.
- Set `invalidateEvent` to control how strictly events interact with invalid ranges: `'strict'` (the default) blocks any overlap with an invalid range; `'start-end'` allows overlap but prevents the event start or end from landing on an invalid range.
- `onEventCreateFailed` and `onEventUpdateFailed` (Vue: `@event-create-failed`, `@event-update-failed`) fire when Mobiscroll blocks a creation or move due to an invalid date.
- Load events from a remote endpoint using `getJson` and assign them to `data`; for the imperative API, call `inst.setEvents(events)` in the callback.

## 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 and Drop Between Calendars](https://demo.mobiscroll.com/vue/eventcalendar/drag-drop-between-calendar-instances.md) - Drag and drop events between two side-by-side Vue event calendar in month view — move events across separate calendars with cross-calendar drag and drop.
- Next: [Double Booking Prevention](https://demo.mobiscroll.com/vue/eventcalendar/prevent-double-booking-events.md) - Prevent overlapping events in a Vue event calendar — block double bookings per event or across all events with in-calendar conflict alerts.
