---
title: "Javascript Date & Time Disabled values Example | Mobiscroll"
component: "Date & Time"
framework: "JavaScript"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/javascript/datetime/disabled-invalid-values"
---

# Disabled values - JavaScript Date & Time demo

Javascript datepicker example for setting invalid days, disabling dates, weekends, holidays, specific and recurring dates. Plain JavaScript API.

- [Live demo](https://demo.mobiscroll.com/javascript/datetime/disabled-invalid-values)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-javascript/tree/main/src/demos/datepicker/datetime/disabled-invalid-values)
- This demo in other frameworks: [jQuery](https://demo.mobiscroll.com/jquery/datetime/disabled-invalid-values.md), [Angular](https://demo.mobiscroll.com/angular/datetime/disabled-invalid-values.md), [React](https://demo.mobiscroll.com/react/datetime/disabled-invalid-values.md), [Vue](https://demo.mobiscroll.com/vue/datetime/disabled-invalid-values.md)

## Description

Enforcing validation is essential to a great UX. First make sure to have the [min & max values right](https://demo.mobiscroll.com/javascript/datetime/min-max-restrictions) and then work your way through disabled values.

Depending on your situation, you have two options:

- **Set invalid** - set the invalids through the [`invalid`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-invalid) option.
- **Set valid** - set the valids through the [`valid`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-valid) option.

Both the [`invalid`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-invalid) and [`valid`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-valid) options support the following:

- **Exact dates** - Passing exact values like: `'2020-05-20'` will disable/enable the specific day
- **Date ranges** - Passing `start` and `end` value pairs will disable/enable specific days and/or times that fall into that range
- **Recurring dates** - Passing recurrence rules as objects or in RRULE string format will be parsed. For [more information on recurrence check out the rule generator](https://demo.mobiscroll.com/javascript/datetime/recurring-values)

Exact dates and the start/end pairs can be passed as [JS date objects, ISO date strings or Moment.js objects](https://demo.mobiscroll.com/javascript/datetime/date-object-ISO-8601-moment). Having invalids set up correctly not just enhances the UX, but improves performance.

## What this demo shows

- Shows a wheel-style inline date picker with disabled values.
- **Display mode** A segmented control on the left side of the picker switches between a date, time list, time grid and date and time picker layout. The date picker is selected by default.
- **Control panel** Below the picker-mode segmented control, users can switch between defining invalid values, selected by default, and setting valid rules. They can configure exact dates, recurring dates such as weekends or holidays, and one or more date ranges.
- **Inline date picker** The example embeds the picker directly in the page without an input by using inline display mode.
- **Date selection** Separate scrollable wheels let users select the month, day, and year. The selected values appear in a central selection area, while neighboring values remain visually subdued.
- **Disabled values** Disabled dates cannot be selected in the picker or from the date and time picker. Disabled times cannot be selected in the time pickers.
- **Scrolling behavior** Users can scroll vertically through neighboring values to move between dates, including dates in other months or years.

## Best for

- **Appointment booking** Prevent customers from selecting dates when a business is closed, fully booked, or unavailable.
- **Employee leave requests** Block weekends, company holidays, and dates outside an allowed request period.
- **Travel and accommodation booking** Disable sold-out dates, unavailable arrival dates, or maintenance periods.
- **Delivery scheduling** Exclude non-delivery days, public holidays, and dates when capacity is unavailable.
- **Course and event registration** Restrict selection to scheduled session dates and disable dates after registration closes.

## Tutorial

- (x) Date
- ( ) Time list
- ( ) Time grid
- ( ) Date & time

### Do you want to

- (x) Set invalid values
- ( ) Set valid values

### Disable exact dates

- [x] Disable these days

`2026-10-24, 2026-10-27`

### Disable recurring dates

- [x] Disable weekends
- [ ] Disable holidays (Christmas Eve, New Years)
- [ ] Disable the first and last of every month

### Disable one or more date ranges

- [x] Disable this range

`2026-10-29 - 2026-11-05`

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['date'],
    invalid: [
		'2026-10-24',
		'2026-10-27',
		{
			start: '2026-10-29',
			end: '2026-11-05'
		},
		{
			recurring: {
				repeat: 'weekly',
				weekDays: 'SA,SU'
			}
		}
	]
});
```

With "Time list":

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['time'],
    invalid: [
		{
			start: '11:30',
			end: '11:30',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '18:00',
			end: '18:00',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '13:00',
			end: '14:00',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '15:00',
			end: '15:30',
			recurring: {
				repeat: 'daily'
			}
		}
	]
});
```

With "Time grid":

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['timegrid'],
    invalid: [
		{
			start: '03:00',
			end: '03:00',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '08:30',
			end: '08:30',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '11:30',
			end: '11:30',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '18:00',
			end: '18:00',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '02:00',
			end: '06:30',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '13:00',
			end: '14:00',
			recurring: {
				repeat: 'daily'
			}
		},
		{
			start: '15:00',
			end: '15:30',
			recurring: {
				repeat: 'daily'
			}
		}
	]
});
```

With "Date & time":

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['datetime'],
    invalid: [
		{
			start: '2022-04-28T09:00',
			end: '2022-04-28T09:00'
		},
		{
			start: '2022-04-30T11:30',
			end: '2022-04-30T11:30'
		},
		{
			start: '2022-04-01T09:00',
			end: '2022-04-01T18:30'
		},
		{
			start: '2022-04-02T15:00',
			end: '2022-04-02T19:00'
		}
	]
});
```

With "Set valid values":

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['date'],
    valid: [
		'2026-10-24',
		'2026-10-27',
		{
			start: '2026-10-29',
			end: '2026-11-05'
		},
		{
			recurring: {
				repeat: 'weekly',
				weekDays: 'MO, TU, WE, TH, FR'
			}
		}
	]
});
```

With "Disable these days" off:

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['date'],
    invalid: [
		{
			start: '2026-10-29',
			end: '2026-11-05'
		},
		{
			recurring: {
				repeat: 'weekly',
				weekDays: 'SA,SU'
			}
		}
	]
});
```

With "Disable weekends" off:

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['date'],
    invalid: [
		'2026-10-24',
		'2026-10-27',
		{
			start: '2026-10-29',
			end: '2026-11-05'
		}
	]
});
```

With "Disable holidays (Christmas Eve, New Years)" on:

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['date'],
    invalid: [
		'2026-10-24',
		'2026-10-27',
		{
			recurring: {
				repeat: 'yearly',
				day: 24,
				month: 12
			}
		},
		{
			recurring: {
				repeat: 'yearly',
				day: 31,
				month: 12
			}
		},
		{
			start: '2026-10-29',
			end: '2026-11-05'
		},
		{
			recurring: {
				repeat: 'weekly',
				weekDays: 'SA,SU'
			}
		}
	]
});
```

With "Disable the first and last of every month" on:

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['date'],
    invalid: [
		'2026-10-24',
		'2026-10-27',
		{
			recurring: {
				repeat: 'monthly',
				day: 1
			}
		},
		{
			recurring: {
				repeat: 'monthly',
				day: -1
			}
		},
		{
			start: '2026-10-29',
			end: '2026-11-05'
		},
		{
			recurring: {
				repeat: 'weekly',
				weekDays: 'SA,SU'
			}
		}
	]
});
```

With "Disable this range" off:

```js
mobiscroll.datepicker('#mydatepicker', {
    controls: ['date'],
    invalid: [
		'2026-10-24',
		'2026-10-27',
		{
			recurring: {
				repeat: 'weekly',
				weekDays: 'SA,SU'
			}
		}
	]
});
```

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-themeVariant) - option
- [`controls`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-controls) - option
- [`display`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-display) - option
- [`invalid`](https://mobiscroll.com/docs/javascript/datepicker/api#opt-invalid) - option

## Code

### JS

```js
mobiscroll.setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

mobiscroll.datepicker('#demo', {
  controls: ['date'],
  display: 'inline',
  invalid: [
    '2020-02-12',
    '2020-05-20',
    {
      recurring: {
        repeat: 'weekly',
        weekDays: 'SA,SU',
      },
    },
    {
      recurring: {
        repeat: 'yearly',
        day: 24,
        month: 12,
      },
    },
    {
      recurring: {
        repeat: 'yearly',
        day: 31,
        month: 12,
      },
    },
    {
      recurring: {
        repeat: 'monthly',
        day: 1,
      },
    },
    {
      recurring: {
        repeat: 'monthly',
        day: -1,
      },
    },
    {
      start: '2020-03-15',
      end: '2020-03-30',
    },
    {
      start: '2020-07-05',
      end: '2020-08-20',
    },
  ],
});
```

### HTML

```html
<div id="demo"></div>
```

## Implementation notes

- **Picker mode** The single `Datepicker` instance's `controls` value can be changed at runtime between `['date']`, `['time']`, `['timegrid']`, and `['datetime']` via `setOptions`.
- **Invalid vs. valid** `invalid` disables listed dates/times (everything else stays selectable); `valid` restricts selection to only the listed dates/times. Only one of `invalid`/`valid` is set at a time - the other is passed as `undefined` via `setOptions`.
- **Exact dates** Individual dates for `invalid`/`valid` are passed as `'YYYY-MM-DD'` strings (formattable via `mobiscroll.formatDate`).
- **Recurring dates** Recurring rule entries can be combined in the `invalid`/`valid` array, e.g. weekends `{ recurring: { repeat: 'weekly', weekDays: 'SA,SU' } }`, weekdays `{ recurring: { repeat: 'weekly', weekDays: 'MO,TU,WE,TH,FR' } }`, holidays as two yearly rules `{ recurring: { repeat: 'yearly', day: 24, month: 12 } }` / `{ recurring: { repeat: 'yearly', day: 31, month: 12 } }`, and first/last of month `{ recurring: { repeat: 'monthly', day: 1 } }` / `{ recurring: { repeat: 'monthly', day: -1 } }` (a negative `day` counts back from the end of the month).
- **Date ranges** A range entry is passed as a `{ start, end }` pair (e.g. formatted `'YYYY-MM-DD'`) merged into the `invalid`/`valid` array.
- **Exact times** In time-list mode, individual times (e.g. `'11:30'`, `'18:00'`) each become `{ start: time, end: time, recurring: { repeat: 'daily' } }` entries.
- **Time ranges** `start - end` time-of-day pairs (e.g. `'13:00 - 14:00'`) become `{ start, end, recurring: { repeat: 'daily' } }` entries; the same exact-time/time-range entry shapes apply independently for time-grid mode (`timegrid`).
- **Exact datetimes and datetime ranges** In date & time mode, full ISO 8601 datetime strings (e.g. `'2022-04-28T09:00'`) and `start - end` datetime pairs produce `{ start, end }` objects, or, when only a time-of-day is given, `{ start: time, end: time, recurring: { repeat: 'daily' } }`.
- The `invalid`/`valid` array (and `controls`, when switching mode) can be updated at runtime via `.setOptions({ invalid: [...] })`, `.setOptions({ valid: [...] })`, and `.setOptions({ controls: [...] })` on the datepicker instance.
- Dates/times covered by `invalid` render disabled and cannot be selected; when `valid` is set, only the listed dates/times remain selectable.

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

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 javascript --trial`.

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

## Related demos

- Previous: [Min & max values](https://demo.mobiscroll.com/javascript/datetime/min-max-restrictions.md) - Javascript date time picker & scroller with min/max restrictions, DOB picker, custom header text for instructions.
- Next: [Recurring values](https://demo.mobiscroll.com/javascript/datetime/recurring-values.md) - Learn how to create recurring rules, RRULE and use them for disabling dates on the Javascript date & time picker.
