DateTimePicker
DateTimePicker
component for entering date and time
Usual date selection
You can choose an arbitrary date (By default, the picker works in calendar mode with a choice of the day of the month)
<template>
<AppDateTimePicker v-model="model" placeholder="Select date" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script>
<template>
<AppDateTimePicker v-model="model" placeholder="Select date" />
</template>
<script>
export default {
data() {
return {
model: null,
};
},
};
</script>
Selecting the date and time
By passing the type=‘datetime’
attribute, you will switch the picker to the mode when you can select the date and time
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
placeholder="Select date"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script>
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
placeholder="Select date"
/>
</template>
<script>
export default {
data() {
return {
model: null,
};
},
};
</script>
Selecting a date range
By passing the type=‘daterange’
or type=‘datetimerange’
attribute, the picker will switch to the mode of selecting a date range or date and time
<template>
<AppDateTimePicker
v-model="dateRange"
type="daterange"
start-placeholder="Start date"
end-placeholder="End date"
/>
<AppDateTimePicker
v-model="dateTimeRange"
type="datetimerange"
start-placeholder="Start date"
end-placeholder="End date"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const dateRange = ref(null);
const dateTimeRange = ref(null);
</script>
<template>
<AppDateTimePicker
v-model="dateRange"
type="daterange"
start-placeholder="Start date"
end-placeholder="End date"
/>
<AppDateTimePicker
v-model="dateTimeRange"
type="datetimerange"
start-placeholder="Start date"
end-placeholder="End date"
/>
</template>
<script>
export default {
data() {
return {
dateRange: null,
dateTimeRange: null,
};
},
};
</script>
Modes ^0.1.0
You can configure the calendar mode you need
day
- the initial display of the calendar of days of the month (it is also possible to select a month or year)month
- the initial display of the calendar of months of the year (it is also possible to select the year)year
- start display of the calendar of years of the decade
INFO
Note that the value that will be emitted will be a date, not a number
To correctly display the value in the input, pass the appropriate format using the date-format
attribute
<template>
<AppDateTimePicker
v-model="month"
mode="month"
date-format="MM"
placeholder="Select month"
/>
<AppDateTimePicker
v-model="yearRange"
date-format="yyyy"
type="daterange"
start-placeholder="Start year"
end-placeholder="End year"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const month = ref(null);
const yearRange = ref(null);
</script>
<template>
<AppDateTimePicker
v-model="month"
mode="month"
date-format="MM"
placeholder="Select month"
/>
<AppDateTimePicker
v-model="yearRange"
date-format="yyyy"
type="daterange"
start-placeholder="Start year"
end-placeholder="End year"
/>
</template>
<script>
export default {
data() {
return {
month: null,
yearRange: null,
};
},
};
</script>
Shortcuts
You can set up shortcuts to quickly select a date
<template>
<AppDateTimePicker
v-model="model"
:shortcuts="shortcuts"
placeholder="Select date"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
const shortcuts = [
{
text: 'Today',
value: new Date(),
},
{
text: 'Next Monday',
value: (() => {
const today = new Date();
const nextMonday = new Date(
today.setDate(today.getDate() + ((8 - today.getDay()) % 7 || 7))
);
return nextMonday;
})(),
},
{
text: 'A week later',
value: new Date(new Date().setDate(new Date().getDate() + 7)),
},
];
</script>
<template>
<AppDateTimePicker
v-model="model"
:shortcuts="shortcuts"
placeholder="Select date"
/>
</template>
<script>
export default {
data() {
return {
model: null,
};
},
computed: {
shortcuts: [
{
text: 'Today',
value: new Date(),
},
{
text: 'Next Monday',
value: (() => {
const today = new Date();
const nextMonday = new Date(
today.setDate(today.getDate() + ((8 - today.getDay()) % 7 || 7))
);
return nextMonday;
})(),
},
{
text: 'A week later',
value: new Date(new Date().setDate(new Date().getDate() + 7)),
},
],
},
};
</script>
Default time
You can configure which time will be substituted by default
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
default-time="15:00:00"
placeholder="Select date"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script>
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
default-time="15:00:00"
placeholder="Select date"
/>
</template>
<script>
export default {
data() {
return {
model: null,
};
},
};
</script>
Timezone
The timezone
attribute is used to correct the time in the picker.
WARNING
The Date
object always remains in the local time zone
When a date is selected, the component atomically calculates the difference between the user's local time zone and the time zone specified in timezone and adds or subtracts it from the time of the selected date for the final display.
The same thing happens when the user first selects a date, only in this case the date is returned, adjusted to the user's local time
INFO
Selected Timezone: America/New_York
Your local time: Sat Apr 26 2025 16:22:40 GMT+0000 (Coordinated Universal Time)
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
timezone="America/New_York"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script>
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
timezone="America/New_York"
/>
</template>
<script>
export default {
data() {
return {
model: null,
};
},
};
</script>
Formats
TIP
To learn more about the available formats, follow this link
In this component, you can configure the format of the date that will be displayed in the inputs.
date-format
attribute is responsible for the format that will be displayed in the main input
time-format
attribute is responsible for the format that will be displayed in the time selection in the popover
Using the combine-formats
(default - true
) attribute, you can determine whether it is necessary to combine the date-format
& time-format
format for the main instep (used when the picker works in the time type)
Example when the attribute has a value of false:
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
date-format="yyyy-MM-dd"
time-format="HH-mm-ss"
placeholder="yyyy-MM-dd HH-mm-ss"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script>
<template>
<AppDateTimePicker
v-model="model"
type="datetime"
date-format="yyyy-MM-dd"
time-format="HH-mm-ss"
placeholder="yyyy-MM-dd HH-mm-ss"
/>
</template>
<script>
export default {
data() {
return {
model: null,
};
},
};
</script>
Disabled date
In order to block the date for selection in a picker or when entering into an input, you need to pass a function to the disabledDate
attribute that checks whether the date is blocked
Block a date that is less than the current one:
Range of available dates (2 days before and 2 days after the current date):
<template>
<p>Block a date that is less than the current one:</p>
<AppDateTimePicker
v-model="modelOne"
:disabled-date="isDateDisabledBeforeToday"
placeholder="Select date"
/>
<p>
Range of available dates (2 days before and 2 days after the current date):
</p>
<AppDateTimePicker
v-model="modelTwo"
:disabled-date="isDateNotInRange"
placeholder="Select date"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const modelOne = ref(null);
const modelTwo = ref(null);
function isDateDisabledBeforeToday(date: Date) {
const today = new Date();
today.setHours(0, 0, 0, 0);
return date < today;
}
function isDateNotInRange(date: Date) {
const today = new Date();
today.setHours(0, 0, 0, 0);
const twoDaysBefore = new Date(today);
twoDaysBefore.setDate(today.getDate() - 2);
const twoDaysAfter = new Date(today);
twoDaysAfter.setDate(today.getDate() + 2);
return date <= twoDaysBefore || date >= twoDaysAfter;
}
</script>
<template>
<p>Block a date that is less than the current one:</p>
<AppDateTimePicker
v-model="modelOne"
:disabled-date="isDateDisabledBeforeToday"
placeholder="Select date"
/>
<p>
Range of available dates (2 days before and 2 days after the current date):
</p>
<AppDateTimePicker
v-model="modelTwo"
:disabled-date="isDateNotInRange"
placeholder="Select date"
/>
</template>
<script>
export default {
data() {
return {
modelOne: null,
modelTwo: null,
};
},
methods: {
isDateDisabledBeforeToday(date) {
const today = new Date();
today.setHours(0, 0, 0, 0);
return date < today;
},
isDateNotInRange(date) {
const today = new Date();
today.setHours(0, 0, 0, 0);
const twoDaysBefore = new Date(today);
twoDaysBefore.setDate(today.getDate() - 2);
const twoDaysAfter = new Date(today);
twoDaysAfter.setDate(today.getDate() + 2);
return date <= twoDaysBefore || date >= twoDaysAfter;
},
},
};
</script>
API
Attributes
Name | Description | Type | Default |
---|---|---|---|
v-model / model-value | binding value, if it is an array, the length should be 2 | null / Date / object | null |
date-format | format is designed to display the date in the input data. more | string | yyyy/MM/dd |
time-format | format is for displaying the time in the time input (ie in moredatetime , datetimerange modes) | string | HH:mm:ss |
combine-formats | generate the format for the picker from the date-format & time-format props | boolean | true |
type | which type of picker should be displayed | string | date |
mode ^0.1.0 | in which mode you want to display the calendar. more | string | day |
first-day-of-week | the order of the days of the week in the day calendar | number | 1 |
weekday-format | format of the days of the week displayed in the calendar | string | short |
month-cell-format | format of months displayed in the calendar | string | short |
month-button-format | the format of the month, which is displayed in the button located in the top panel of the calendar | string | long |
shortcuts | list of shortcuts to quickly select a date more | object | [] |
default-time | the time that will be set by default. The expected format is “00:00:00”. more | string / object | " |
locale | the language in which you want to display data in the picker. (Use only if you do not have the vue-i18n package) | string | en |
time-options | setting up the time picker | string | {} |
disabled-date | the option is used to define blocked dates | Function | — |
hide-offset-day ^0.3.0 | hide the days of another month in the calendar | false | false |
auto-apply ^0.2.0 | applying changes without clicking the "Apply" button | boolean | false |
disabled | whether the picker is blocked | boolean | false |
readonly | whether the picker is read-only | boolean | false |
input-readonly ^0.0.2 | switch the inputs to read-only mode, but through the popover it is possible to select the date | boolean | false |
clearable | displaying a controller for clearing a data input when it is full | boolean | false |
timezone | which time zone will be used for date correction. more | string | " |
placeholder | a placeholder that will be displayed in the inpt when the picker is working in single mode | string | " |
start-placeholder | placeholder that will be displayed in the first input when the picker is in range mode | string | " |
end-placeholder | placeholder that will be displayed in the last input when the picker is in range mode | string | " |
align | the position of the popover display | string | left |
start-id ^0.2.0 | id for the first native input (also used for the native input when there is only one) | string | " |
end-id ^0.2.0 | id for the last native input | string | " |
start-name ^0.2.0 | name attribute for the first native input (also used for the native input when there is only one) | string | " |
end-name ^0.2.0 | name attribute for the last native input | string | " |
apply-text | the text displayed in the apply button in the picker popover | string | "Apply" |
cancel-text | the text displayed in the cancel button in the picker popover | string | "Cancel" |
invalid | indicates that the picker has an invalid value | boolean | false |
z-index ^0.3.0 | z-index for popover conent | number | 1000 |
client-only-popover-content ^0.3.0 | Render popover content inside | boolean | false |
open-delay | delay in milliseconds before the popover opens after being triggered | number | 0 |
close-delay | delay in milliseconds before the popover closes after being triggered | number | 150 |
append-to-body | determines if the popover content should be appended to the body instead of being nested within the DOM structure of the component | boolean | true |
stay-opened | leave the picker open after opening it. Use it for debugging or researching a popover | boolean | false |
Events
Name | Description | Type |
---|---|---|
change | triggered when the value was changed | Function |
focus | triggers when picker focuses | Function |
blur | triggered when the picker is no longer in focus | Function |
Slots
Name | Description |
---|---|
default | custom reference for popover |
separator | custom range separator content |
Default slot ^0.0.2
This slot is a replacement for the date entry field. Below is a table with the available props for this slot
Name | Description | Type |
---|---|---|
value | The value that is passed to the input (without formatting) | null / Date / object |
popoverVisible | returns whether the popover is currently open or not | boolean |
input | setting a new value in the picker | Function |
blur | blur the picker component | Function |
focus | focus the picker component | Function |
<template>
<AppDateTimePicker v-model="model">
<template #default="{ value, popoverVisible, input, focus }">
<input
:value="dateToStringDate(value)"
:class="{ 'custom-input--focus': popoverVisible }"
class="custom-input"
placeholder="Select date"
@focus="focus"
@input="event => stringDateToDate(event, input)"
/>
</template>
</AppDateTimePicker>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { format, isDate, parse } from 'date-fns';
const model = ref(null);
const dateFormat = 'yyyy-MM-dd';
function dateToStringDate(value: Date | null) {
if (!value || !isDate(value)) return '';
return format(value, dateFormat);
}
function stringDateToDate(event: InputEvent, cb: (value: unknown) => void) {
const value = (event.target as HTMLInputElement).value;
const parsed = parse(value, dateFormat, new Date());
if (!value) {
cb(null);
}
if (value.length === dateFormat.length && isDate(parsed)) {
cb(parsed);
}
}
</script>
<style lang="scss" scoped>
.custom-input {
width: 100%;
border: 1px solid;
&:focus,
&--focus {
border-color: blue;
}
}
</style>
<template>
<AppDateTimePicker v-model="model">
<template #default="{ value, popoverVisible, input, focus }">
<input
:value="dateToStringDate(value)"
:class="{ 'custom-input--focus': popoverVisible }"
class="custom-input"
placeholder="Select date"
@focus="focus"
@input="event => stringDateToDate(event, input)"
/>
</template>
</AppDateTimePicker>
</template>
<script>
export default {
data() {
return {
model: null,
dateFormat: 'yyyy-MM-dd',
};
},
methods: {
dateToStringDate(value) {
if (!value || !isDate(value)) return '';
return format(value, this.dateFormat);
},
stringDateToDate(event, cb) {
const value = event.target.value;
const parsed = parse(value, this.dateFormat, new Date());
if (!value) {
cb(null);
}
if (value.length === this.dateFormat.length && isDate(parsed)) {
cb(parsed);
}
},
},
};
</script>
<style lang="scss" scoped>
.custom-input {
width: 100%;
border: 1px solid;
&:focus,
&--focus {
border-color: blue;
}
}
</style>
Exposes
Name | Description | Type |
---|---|---|
popoverVisible | returns whether the popover is currently open or not | object |
focus | focus the picker component | Function |
blur | blur the picker component | Function |